/* Arland.ai marketing site.

   Shares colors.css with arland-app so the purple, the grays and the dark
   mode are the same product. Everything below is layout that only the
   marketing site has: a top nav over a centered column, and an editorial
   two column band that repeats down the page — headline in the left
   column, supporting copy dropped lower in the right. */

:root {
    /* Same tokens as arland-style.css, so a button or a field made here
       lands on the same geometry as one in the dashboard. */
    --spacer: 2rem;
    --bubble-radius: 3rem;
    --pill-radius: 999px;
    --field-radius: 0.5rem;

    /* The content measure. px on purpose: it is a target width, not a
       multiple of the body text, so it must not drift when the root
       font-size changes. The widget is overridden to match it below. */
    --measure: 800px;

    /* The page's outer gutter scales with the viewport rather than
       stepping at a breakpoint, so the measure keeps its air all the way
       down to the point where the nav collapses. */
    --gutter: clamp(1.25rem, 3.5vw, 3.5rem);

    /* How far the right-hand column of a band drops below its headline.
       band.du can override it per-band with an inline --band-offset. */
    --band-offset: 1.5rem;

    /* TYPE SCALE — the only sizes on the site.

       1rem is body text and the floor: nothing on the page is set
       smaller than --text-base, so there is no size a rule can nudge
       something down to. Steps are whole steps (1 -> 1.125 -> 1.25 ->
       1.5 -> 2.25), not the 0.05rem adjustments this replaced, which
       were too close together to read as a difference and too many to
       keep straight.

       The two headings are fluid because they are the only text big
       enough for a narrow viewport to care about; everything else is a
       flat rem and scales with the root. */
    --text-base: 1rem;
    --text-md: 1.125rem;
    --text-lg: 1.25rem;
    --text-xl: 1.5rem;
    --text-2xl: 2.25rem;

    --h1: clamp(2rem, 1.35rem + 2.6vw, 3rem);
    --h2: clamp(1.5rem, 1.2rem + 1.4vw, 2rem);

    /* The marketing page sits on a faint gray rather than the near-white
       the app uses — it lets the white chat card lift off it. */
    --page-bg: hsl(240, 6%, 97%);
    --card-bg: hsl(240, 6%, 100%);

    /* The nav sits on the card surface — pure white here, the raised gray
       in dark — rather than on the page's own tint, so the bar reads as a
       fixed edge to the page rather than a strip of it. */
    --nav-bg: hsl(240, 6%, 100%);

    /* Separates the sticky bar from whatever is scrolling under it. Tight
       and shallow on purpose: the nav is an edge to the page, not a card
       floating over it. Stronger in dark mode — four points of lightness
       separate the bar from the page there against white-on-gray's three,
       but the eye reads far less of a step at that end. */
    --nav-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

/* Light's ladder at a much lower lightness, in the same order and the
   same hue, so the two themes are one design at two exposures:

     tertiary  5%  / 88%   the card strip's ground
     secondary 8%  / 92%   the sunk strip, inputs, the bot's chat bubble
     page     10%  / 97%   the page itself
     primary  13%  / 99%   bubbles and other things that lift off it
     card     14%  / 100%  the chat card, the plan cards, the nav

   The bg-* three come from colors.css; the three below are this site's. */
[data-theme="dark"] {
    --page-bg: hsl(240, 6%, 10%);
    --card-bg: hsl(240, 6%, 14%);
    --nav-bg: hsl(240, 6%, 14%);
    --nav-shadow: 0 1px 4px rgba(0, 0, 0, 0.55);
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --page-bg: hsl(240, 6%, 10%);
        --card-bg: hsl(240, 6%, 14%);
        --nav-bg: hsl(240, 6%, 14%);
        --nav-shadow: 0 1px 4px rgba(0, 0, 0, 0.55);
    }
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html {
    /* The reader's default, not a size of our own. 15px here made every
       `1rem` in this file a shade under body text everywhere else, which
       is what the scale above exists to stop. */
    font-size: 100%;
    /* Anchor links land under the sticky nav otherwise. */
    scroll-padding-top: 5rem;
}

body {
    font-family:
        -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu,
        Cantarell, sans-serif;
    font-size: var(--text-base);
    line-height: 1.6;
    background-color: var(--page-bg);
    color: var(--text-primary);
    min-height: 100vh;
    -webkit-font-smoothing: antialiased;
}

nobreak {
    display: inline;
    word-break: none;
}

/* Blue at rest, text color on hover — arland-app's convention, where
   arland-style.css overrides the purple colors.css gives links. It reads
   as a link before the pointer is anywhere near it. */
a {
    color: var(--complement);
    text-decoration: none;
}

a:hover {
    color: var(--text-primary);
    text-decoration: underline;
}

/* NAV — logo left, links right. Sticky: it stays reachable on a long
   page rather than needing a scroll back to the top. */

.nav {
    position: sticky;
    top: 0;
    z-index: 20;
    background-color: var(--nav-bg);
    box-shadow: var(--nav-shadow);
    padding: 0.75rem var(--gutter);

    /* The burger's box and the hit area it pads out. Variables because
       the menu below it lines its rows up on them: the bars are the
       column the marks sit in, and where the wordmark starts is this
       box plus the row's gap. */
    --burger-size: 2.75rem;
    --burger-pad: 0.6rem;
}

.nav-inner {
    max-width: var(--measure);
    margin-inline: auto;
    display: flex;
    align-items: center;
    gap: 1.5rem;
}

.brand {
    display: inline-block;
    font-size: var(--text-xl);
    font-weight: 800;
    letter-spacing: -0.035em;
    color: var(--primary);
    line-height: 1;
    /* Holds the left end of the row; the links take the other. */
    margin-right: auto;
}

.brand-img {
    width: clamp(96px, 9vw, 130px);
    max-width: 100%;
    height: auto;
    display: block;
    margin-bottom: 0.2rem;
}

.brand:hover {
    color: var(--primary);
    opacity: 0.85;
}

.nav-links {
    order: 2;
    margin-top: 0.1rem;
}

.nav-links ul {
    list-style: none;
    display: flex;
    align-items: center;
    gap: 1.5rem;
}

/* Flex, not the inline box an anchor is by default: an inline box's
   vertical padding paints outside the line it sits on, so the pill was
   drawn 0.5rem taller than the row it was being centered in and sat a
   couple of pixels high in it. As a box it has real height, and the row
   is as tall as the tallest thing on it — which since the theme control
   moved to the footer is the pill. */
.nav-links a {
    display: flex;
    align-items: center;
    font-size: var(--text-base);
    font-weight: 500;
    color: var(--complement);
    transition: color 0.15s;
    white-space: nowrap;
}

/* Menu-only: privacy and terms are the footer's job. */
.nav-minor {
    display: none;
}

.nav-links a:hover {
    color: var(--text-primary);
    text-decoration: underline;
}

/* The page you are on is the one link that isn't a link. Text color
   rather than an accent: it reads as present, not as another target. */
.nav-links a[aria-current="page"] {
    color: var(--text-primary);
}

/* The one thing the site is asking for, so it gets the button. */
/* Qualified with the element the generic .nav-links a rule targets:
   that selector is 0,1,1 and a bare .nav-cta is 0,1,0, so the pill lost
   its own padding and color to it. Specificity, not !important. */
.nav-links a.nav-cta {
    padding: 0.5rem 1.1rem;
    border-radius: var(--pill-radius);
    background-color: var(--primary);
    color: #fff;
}

.nav-links a.nav-cta:hover {
    filter: brightness(1.08);
}

/* Menu rows carry a phosphor mark; the bar's row of words does not. */
.nav-icon {
    display: none;
}

/* Bar-only, below the breakpoint: the two things worth a tap without
   opening the menu. Above it the full row is already on screen and these
   would be the same links twice. */

.nav-mobile-actions {
    display: none;
}

/* The menu's copy of the theme toggle. Hidden here; the bar's copy is
   the one on screen at this width. */
.nav-theme {
    display: none;
}

/* THEME TOGGLE — the dashboard's control, same three states and the same
   static/theme.js. The script shows exactly one icon by index, so
   every .theme-icon starts hidden here.

   Two of them, both live: the footer's, and the burger menu's last row.
   Nothing on the nav bar — see html/footer.du. */

.theme-toggle {
    /* A button brings its own font; every place this sits is a row of
       links, so it takes theirs. */
    font: inherit;
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
    display: flex;
    align-items: center;
}

.theme-icon {
    display: none;
    width: 1.25rem;
    height: 1.25rem;
    /* Same as the label beside it, at rest and on hover. */
    color: inherit;
    transition: color 0.3s;
}

/* The mobile menu's open/closed state. A checkbox, not a script: see
   html/nav.du. Off-screen rather than display:none or hidden, both of
   which take it out of the tab order and make the label unreachable by
   keyboard. */

.nav-state {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
    pointer-events: none;
}

.nav-burger {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: var(--burger-size);
    height: var(--burger-size);
    padding: var(--burger-pad);
    cursor: pointer;
    border-radius: var(--field-radius);
}

.nav-burger span {
    display: block;
    height: 2px;
    border-radius: 2px;
    background-color: var(--text-primary);
    transition: transform 0.2s, opacity 0.2s;
}

.nav-state:focus-visible + .nav-burger {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* CONTENT */

.content {
    padding: clamp(2rem, 4vw, 3.5rem) var(--gutter) 5rem;
    max-width: calc(var(--measure) + 2 * var(--gutter));
    margin-inline: auto;
}

/* STRIPS — the home page only.

   Every other page is one centered column: .content holds the measure and
   the gutters, and the page has one background from top to bottom. The
   home page instead stacks full-width sections that each carry their own
   background, which means the element holding the measure cannot also be
   the element being painted — a background can only run edge to edge if
   the box it is on does.

   So on the home page main gives up both and .strip-inner takes them
   over, at exactly .content's geometry, so a band inside a strip lands
   where a band on any other page lands. No 100vw breakout: that measures
   the viewport including the scrollbar and overflows by its width. */

.content-strips {
    /* main is a bare stack here — strips bring their own spacing. */
    padding: 0;
}

.strip {
    padding-block: clamp(3rem, 7vw, 5rem);
}

/* The hero keeps the tighter top .content gives every other page: it
   opens under the nav, so there is nothing above it to be separated
   from. */
.strip:first-child {
    padding-top: clamp(2rem, 4vw, 3.5rem);
}

.strip-inner {
    max-width: calc(var(--measure) + 2 * var(--gutter));
    margin-inline: auto;
    padding-inline: var(--gutter);
}

/* A band's bottom margin is what separates it from the next band. The
   last thing in a strip is separated by the strip's own padding
   instead, and both would double the gap. */
.strip-inner > :last-child {
    margin-bottom: 0;
}

/* THE THREE TONES.

   Named for what they do to the page rather than for a color: "white"
   is only true in one of the two themes, and the point of taking these
   from colors.css is that each one flips on its own.

     plain — the page's own faint gray, nothing painted
     card  — lifts: white in light mode, the raised near-black in dark
     sunk  — settles: one step down from the page in both themes

   They are meant to alternate rather than run in order of intensity, so
   the page reads as a rhythm and not as a gradient. */

.strip-plain {
    background-color: transparent;
}

.strip-primary {
    background-color: var(--nav-bg);
}

.strip-card {
    background-color: var(--bg-tertiary);
}

.strip-sunk {
    background-color: var(--bg-secondary);
}

/* FOOTER — the same page, further down. No rule and no background of its
   own: a divider would make it a separate region and stop the eye there.
   The gap is what separates it. */

.foot {
    max-width: calc(var(--measure) + 2 * var(--gutter));
    margin-inline: auto;
    padding: 2rem var(--gutter);

    /* The step between one thing and the next, both columns. Inside a
       thing there is no step at all: the rows are line boxes, so the
       links stack on the same rhythm as the lines the left column wraps
       to, and both columns break at the same distance. */
    --foot-gap: 0.75rem;
}

/* Two even columns: the notice on the left, the links stacked on the
   right. Even, and not sized to their contents — the halves are what
   make the credits wrap into a paragraph instead of running the width of
   the page and holding the links out at arm's length. */
.foot-inner {
    display: grid;
    grid-template-columns: 1fr 1fr;
    align-items: start;
    gap: 1rem 3rem;
}

/* The pitch and the small print, in that order: what this is, then who
   owns it and what it runs on. */
.foot-about {
    display: flex;
    flex-direction: column;
    gap: var(--foot-gap);
}

.foot-pitch {
    font-size: var(--text-base);
    color: var(--text-secondary);
}

.foot-pitch strong {
    color: var(--text-primary);
}

.foot-copy {
    font-size: var(--text-base);
    color: var(--text-muted);
}

.foot-copy a {
    color: var(--complement);
}

.foot-copy a:hover {
    color: var(--text-primary);
    text-decoration: underline;
}

/* Stacked, at any width: two legal links and a control, one per line —
   and one line means one line, body line-height and nothing between the
   rows, so they land on the notice's lines beside them. */
.foot-links {
    list-style: none;
    display: flex;
    flex-direction: column;
}

/* Not one of the links — the gap says so, and it is the same step the
   left column puts between the pitch and the credits. */
.foot-theme {
    margin-top: var(--foot-gap);
}

/* Icon first, then the label, on one line box: the row stays the height
   of its text so the column keeps the notice's rhythm beside it. */
.foot-links a {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: var(--text-base);
    color: var(--complement);
}

.foot-icon {
    flex: none;
    width: 1.25rem;
    height: 1.25rem;
    color: inherit;
}

.foot-links a:hover {
    color: var(--text-primary);
    text-decoration: underline;
}

.foot-links a[aria-current="page"] {
    color: var(--text-primary);
}

/* The theme control reads as one more link in the column, icon first,
   the way the burger menu's last row does — and on the same line box, so
   the icon does not push the row taller than the text beside it. */
.foot-theme .theme-toggle {
    gap: 0.5rem;
    font-size: var(--text-base);
    line-height: inherit;
    color: var(--complement);
}

.foot-theme .theme-toggle:hover {
    color: var(--text-primary);
    text-decoration: underline;
}

/* BAND — the repeating two column unit.

   Left column carries the headline, right column the supporting copy,
   dropped by --band-offset so the page reads as a diagonal rather than
   two parallel blocks. Anything that should span both (the chat demo,
   a table) goes in .band-full. */

.band {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 0;
    row-gap: var(--band-offset);
    margin-bottom: 4rem;
    max-width: var(--measure);
    margin-inline: auto;
}

.band-title {
    grid-column: 1;
    grid-row: 1;
    text-align: right;
    font-size: var(--h1);
    font-weight: 800;
    line-height: 1.1;
    color: var(--text-primary);
}

.band-body {
    grid-column: 2;
    grid-row: 2;
    /* A step above body text. The right column is the line that has to
       be read, so it is never the smallest thing in the band. */
    font-size: var(--text-md);
    font-weight: 500;
    line-height: 1.5;
    color: var(--text-secondary);
}

/* The lead band's supporting line is the page's subhead, so it takes one
   more step up. This is the only band body that differs.

   .band-lead, not :first-of-type — band.du sets the class from the same
   fact that picks the heading tag. On the home page each band is the only
   band inside its own strip, so every one of them is a :first-of-type and
   a positional selector would size all four as the lead. */
.band-lead .band-body {
    font-size: var(--text-lg);
}

/* Which is also why the headline is sized off its own tag: h1 is the lead
   band's, h2 is every other band's, and .band-title above already set the
   h1 size for both. */
h2.band-title {
    font-size: var(--h2);
}

.band-body p + p {
    margin-top: 1rem;
}

.band-body a {
    color: var(--complement);
    text-decoration: underline;
    text-underline-offset: 0.15rem;
}

.band-body a:hover {
    color: var(--text-primary);
}

/* A headline over one thing, centered, no second column. See band.solo. */
.band-solo {
    max-width: var(--measure);
    margin-inline: auto;
    margin-bottom: 4rem;
}

.band-solo-title {
    font-size: var(--h2);
    font-weight: 800;
    line-height: 1.1;
    text-align: center;
    color: var(--text-primary);
    margin-bottom: 2rem;
}

.band-full {
    grid-column: 1 / -1;
    /* The grid's own row-gap (--band-offset, up to 4rem on a page that
       sets one) already separates this from the copy above it. 3rem on
       top of that put a headline and the thing it introduces far enough
       apart to read as two unrelated sections. */
    margin-top: 0.5rem;
}

/* .steps, .plans, .benefits, .features and .faq each carry a top margin
   for standing on their own. Dropped in a band they are the third grid
   row, and that margin stacked on the row-gap above it — which is where
   most of the hole under a headline was actually coming from. */
.band-full > :first-child {
    margin-top: 0;
}

/* Sub pages run their bands flat — one column, headline left, copy
   straight under it. layout.du puts .content-flat on every page but the
   home page. The stagger is the landing page's signature; on pricing it
   would only push the plans further down. */

.content-flat .band {
    grid-template-columns: minmax(0, 1fr);
    /* --band-offset exists to deepen the diagonal. There is no diagonal
       here, so a page that set one (pricing passes 4) would otherwise
       just get a hole under its headline. */
    row-gap: 1.5rem;
}

.content-flat .band-title {
    grid-column: 1;
    grid-row: 1;
    text-align: left;
    padding-right: 0;
}

.content-flat .band-body {
    grid-column: 1;
    grid-row: 2;
    padding-left: 0;
    /* The band is 50rem wide for the tables and card grids that sit in
       .band-full; a paragraph wants the same measure the prose pages
       use, not the full width. */
    max-width: 38rem;
}

/* Pages that are just prose (privacy, terms) drop the split entirely and
   run one readable measure under a left-aligned headline. */

.page-prose {
    margin-bottom: 4rem;
}

.page-prose > h1 {
    /* Same curve as .band-title so a legal page's headline and the home
       page's are the same size at the same viewport. */
    font-size: var(--h1);
    font-weight: 800;
    letter-spacing: -0.04rem;
    line-height: 1.05;
    color: var(--text-primary);
}

/* Full measure, like every other page. A 38rem column left-aligned in an
   800px content area read as a page that had failed to fill itself, and
   the empty right-hand third was the most noticeable thing on it.

   The measure is wide for continuous prose, so the line-height goes up to
   carry it: a long line is only hard to read when the eye loses which row
   it is returning to, and leading is what fixes that. */
.band-prose {
    margin-top: 2rem;
    line-height: 1.75;
    color: var(--text-secondary);
}

.band-prose h2 {
    font-size: var(--text-xl);
    font-weight: 700;
    letter-spacing: -0.02rem;
    color: var(--text-primary);
    margin: 2.5rem 0 0.75rem;
}

.band-prose h3 {
    font-size: var(--text-md);
    font-weight: 700;
    color: var(--text-primary);
    margin: 1.75rem 0 0.5rem;
}

.band-prose p,
.band-prose li {
    margin-bottom: 1rem;
}

.band-prose ul,
.band-prose ol {
    margin: 0 0 1rem 1.25rem;
}

.band-prose a {
    color: var(--complement);
    text-decoration: underline;
    text-underline-offset: 0.15rem;
}

.band-prose a:hover {
    color: var(--text-primary);
}

.band-prose em {
    color: var(--text-muted);
}

/* ASK — the chat demo.

   An outer card holding the field and the suggestion chips, matching the
   mockup: pill field with a filled circular send button inside it, chips
   in a row underneath. The transcript is inserted above the field by
   htmx, so an empty demo is exactly the mockup and a used one grows
   upward from the same box. */

/* The scroll-stopper. Left, so the arrow comes down on the field itself
   rather than on the send button at the other end — the ask is for them
   to type something, and a cue pointing at the button says the opposite.
   Hard against the widget too: a gap here would read as a heading for the
   whole section instead of a label on the box. */
.ask-cue {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 0.6rem;
    /* Lines the text up over the placeholder rather than the card's edge:
       .ask has 1rem of padding and .ask-form another 1.25rem before its
       input starts. */
    padding-left: 2.25rem;
    font-size: var(--text-lg);
    font-weight: 700;
    line-height: 1;
    color: var(--primary);
}

.ask-cue-icon {
    width: 1.75rem;
    height: 1.75rem;
    /* The arrow points at the field, so it is the half that moves. Small
       and slow: enough to catch the eye mid-scroll, not enough to keep
       pulling at it once someone has stopped. Killed outright by the
       reduced-motion block at the foot of this file. */
    animation: ask-cue-nudge 2.4s ease-in-out infinite;
}

@keyframes ask-cue-nudge {
    0%, 60%, 100% { transform: translateY(0); }
    75% { transform: translateY(0.3rem); }
}

.ask {
    background-color: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--bubble-radius);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 8px 24px rgba(0, 0, 0, 0.05);
    padding: 1rem;
    /* Spans .band-full rather than stopping short of it — the placeholder
       has to have the real widget's footprint or the page jumps on mount. */
    max-width: 100%;
}

/* The real widget's :host sets width:100%, max-width:52rem, margin:0 auto.
   That rem resolves against the document root, so it moves whenever the
   root font-size does, and it caps the widget short of the measure. The
   host is a light-DOM div.arland-widget the embed script inserts, and an
   outer-page rule beats a :host declaration in the cascade. */
#arland-widget > .arland-widget {
    max-width: var(--measure);
    margin-inline: auto;
}

.ask-log {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding: 0.5rem 0.5rem 1rem;
}

/* No rows yet means no padding — the card has to collapse back to the
   mockup's height when the demo has not been used. */
.ask-log:empty {
    display: none;
}

.ask-turn {
    max-width: 85%;
    padding: 0.6rem 1rem;
    border-radius: var(--bubble-radius);
    font-size: var(--text-base);
    line-height: 1.5;
}

.ask-turn-you {
    align-self: flex-end;
    background-color: var(--primary);
    color: white;
    border-bottom-right-radius: 0.5rem;
}

.ask-turn-arland {
    align-self: flex-start;
    background-color: var(--bg-secondary);
    color: var(--text-primary);
    border-bottom-left-radius: 0.5rem;
}

.ask-turn-arland a {
    color: var(--complement);
    text-decoration: underline;
}

.ask-turn-arland a:hover {
    color: inherit;
}

.ask-form {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background-color: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--pill-radius);
    padding: 0.35rem 0.35rem 0.35rem 1.25rem;
}

.ask-form:focus-within {
    border-color: var(--primary);
    box-shadow: 0 0 0 3px var(--primary-lighter);
}

.ask-input {
    flex: 1 1 auto;
    min-width: 0;
    border: none;
    background: none;
    color: var(--text-primary);
    font-family: inherit;
    font-size: var(--text-md);
    line-height: 2.25rem;
    padding: 0;
}

.ask-input:focus {
    outline: none;
}

.ask-input::placeholder {
    color: var(--text-muted);
}

.ask-send {
    flex: 0 0 auto;
    width: 2.5rem;
    height: 2.5rem;
    display: grid;
    place-items: center;
    padding: 0;
    border: none;
    border-radius: 50%;
    background-color: var(--primary);
    color: white;
    cursor: pointer;
    transition: filter 0.15s;
}

.ask-send:hover {
    filter: brightness(var(--hover-brightness));
}

.ask-send svg {
    width: 1.25rem;
    height: 1.25rem;
    display: block;
}

.ask-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    padding: 0.75rem 0.25rem 0.25rem;
}

.ask-chip {
    /* Basis rather than auto: the chips share the row while they fit,
       then wrap 3 -> 2 -> 1 on their own. No breakpoint flips them to a
       column, so there is no width where they jump from a tidy row to a
       stack of full-width bars. */
    flex: 1 1 8.5rem;
    padding: 0.55rem 1.25rem;
    border: 1px solid var(--border);
    border-radius: var(--pill-radius);
    background: none;
    color: var(--text-secondary);
    font-family: inherit;
    font-size: var(--text-base);
    font-weight: 500;
    cursor: pointer;
    transition: border-color 0.15s, color 0.15s;
}

.ask-chip:hover {
    border-color: var(--primary);
    color: var(--primary);
}

/* htmx marks the element it is about to swap into with .htmx-request
   while a request is out. Dim the card so a slow answer looks like a
   wait rather than a dead button. */
.ask.htmx-request .ask-form,
.ask.htmx-request .ask-chips {
    opacity: 0.55;
}

/* CODE — the install snippet. */

.snippet {
    background-color: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--field-radius);
    padding: 1rem 1.25rem;
    overflow-x: auto;
    font-size: var(--text-base);
    line-height: 1.6;
    color: var(--text-primary);
    max-width: 44rem;
}

.snippet code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    white-space: pre;
}

/* STEPS — numbered list under "Install in your site in minutes". */

.steps {
    list-style: none;
    display: grid;
    gap: 1.5rem;
    max-width: 44rem;
    margin-top: 2rem;
}

.step {
    display: grid;
    grid-template-columns: 2.25rem minmax(0, 1fr);
    gap: 1rem;
    align-items: start;
}

.step-n {
    width: 2.25rem;
    height: 2.25rem;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background-color: var(--primary);
    color: white;
    font-weight: 700;
    font-size: var(--text-base);
}

.step h3 {
    font-size: var(--text-md);
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 0.15rem;
}

.step p {
    color: var(--text-secondary);
    font-size: var(--text-base);
}

/* BENEFITS — the card grid on the sunk strip.

   Same card language as .plan: card background, border, bubble radius.
   The two grids on the site are the same kind of object, so they are made
   of the same parts. auto-fit rather than a fixed column count, so the
   grid reflows 3 -> 2 -> 1 on its own and neither breakpoint below has to
   know how many cards the page passed. */

.benefits {
    list-style: none;
    display: grid;
    /* 17rem, so three columns do not fit the 800px measure and the grid
       settles at two. Six cards three-up inside this measure leaves each
       one about 250px wide, which is narrow enough to break every heading
       across two lines. */
    grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr));
    gap: 1.5rem;
    margin-top: 2rem;
}

.benefit {
    background-color: var(--bg-primary);
    border: 1px solid var(--border);
    /* Not --bubble-radius: these are the smallest boxes on the site, and
       the plan cards' curve on one of them eats the corner it turns. */
    border-radius: 2rem;
    padding: 1.75rem;
    /* The mark gets a column of its own, so the heading and the body share
       one left edge and the icon never sits on top of the text it belongs
       to. align-items: start keeps it level with the heading rather than
       floating in the middle of a card the next one is taller than. */
    display: grid;
    grid-template-columns: 2.75rem minmax(0, 1fr);
    column-gap: 1.25rem;
    align-items: start;
    /* The cards stretch to match the tallest in their row, and a grid with
       free space hands it to its auto rows — which pushed the body away
       from a one-line heading and left it under a two-line one. Pack the
       rows at the top and let the spare height fall to the bottom of the
       card, where nothing is reading it. */
    align-content: start;
}

/* Spans both columns from row two down, under the heading — the icon
   holds row one of column one and nothing else needs to clear it. */
.benefit h3,
.benefit p {
    grid-column: 2;
}

/* The one purple thing in the card. The heading and the body stay in the
   text colors, so the mark is what the eye lands on first. */
.benefit-icon {
    grid-row: span 2;
    width: 2.75rem;
    height: 2.75rem;
    color: var(--primary);
}

.benefit h3 {
    font-size: var(--text-lg);
    font-weight: 700;
    letter-spacing: -0.01em;
    line-height: 1.25;
    color: var(--text-primary);
    margin-bottom: 0.5rem;
}

.benefit p {
    font-size: var(--text-base);
    line-height: 1.5;
    color: var(--text-secondary);
}

/* FEATURES — the complete list, grouped, one line per fact.

   Not cards. The benefits above are six separate claims and are boxed to
   say so; this is one list in six columns, and boxing it would make six
   arguments out of what is meant to read as one inventory. */

.features {
    display: grid;
    /* Two columns, never three. Three inside the 800px measure left each
       one about 245px, which broke most lines across two and turned a
       scannable list into a wall. The gutter is wide because it is the
       only thing separating the columns — there is no rule between them,
       so the whitespace has to be unmistakable. */
    grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
    gap: 2.75rem 4rem;
    margin-top: 2rem;
}

.feature-group h3 {
    font-size: var(--text-md);
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--text-primary);
    padding-bottom: 0.6rem;
    margin-bottom: 0.9rem;
}

.feature-group ul {
    list-style: none;
    display: grid;
    gap: 0.55rem;
    font-size: var(--text-base);
    line-height: 1.4;
    color: var(--text-secondary);
}

/* The check sits in its own column so a line that wraps stays aligned
   under its own first word rather than tucking under the mark. */
.feature-group li {
    display: grid;
    /* The mark's column hugs the mark, and the gap is the gap — a fixed
       column wide enough to hold both was setting the space between them
       by subtraction. */
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: 0.5rem;
    align-items: start;
}

.feature-group li::before {
    content: "✓";
    color: var(--primary);
    font-weight: 700;
}

/* A tier-limited line says so on the line itself — the alternative is a
   footnote, and a footnote is where someone finds out after deciding. */
.feature-pro {
    display: inline-block;
    margin-left: 0.35rem;
    padding: 0.05rem 0.45rem;
    border-radius: var(--pill-radius);
    background-color: var(--primary);
    color: #fff;
    font-size: 0.75em;
    font-weight: 700;
    letter-spacing: 0.02em;
    vertical-align: 0.08em;
}

/* PLANS */

/* THE BILLING SWITCH — a segmented control, no script.

   Two radios drive everything: a thumb that slides under the chosen word,
   and which of the two prices in each card is showing. Radios rather than
   a checkbox because clicking "Monthly" must mean monthly — a checkbox
   label toggles, so clicking the word you are already on would flip you
   off it.

   The inputs themselves live outside .cycle, as siblings of .plans: a
   checked input can only style what comes after it, and what comes after
   it has to include the cards. */

/* Hidden, but still focusable and still first in #plans — which is also
   where the switch they drive is drawn. That matters: clicking a
   <label for> focuses its input, and a browser scrolls a focused element
   into view, so a radio parked any distance from its own control drags
   the page there on every click. Here the two are the same place and
   there is nothing to scroll to.

   The focus ring shows on .cycle, drawn by the rule below. */
.cycle-input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
    pointer-events: none;
}

/* Switch centered under the two cards, its note stacked underneath and
   centered with it. Side by side, the note read as a caption on the
   control; under it, it reads as what the control is offering.

   Above the cards, and the strip's own padding is the space over it. */
.cycle-row {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
}

.cycle {
    position: relative;
    display: inline-flex;
    padding: 0.3rem;
    border-radius: var(--pill-radius);
    border: 1px solid var(--border);
    background-color: var(--bg-primary);
}

/* The focus ring belongs to the whole control: the inputs are off-screen,
   so a ring on them would be invisible while they are what is focused. */
.cycle-input:focus-visible ~ .cycle-row .cycle {
    outline: 2px solid var(--primary);
    outline-offset: 3px;
}

/* Half the track, inset by its padding — so translateX(100%) lands it
   exactly on the second word however wide the two of them are. */
.cycle-thumb {
    position: absolute;
    z-index: 0;
    top: 0.3rem;
    bottom: 0.3rem;
    left: 0.3rem;
    width: calc(50% - 0.3rem);
    border-radius: var(--pill-radius);
    background-color: var(--primary);
    transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Yearly is drawn first, so the thumb starts on it and travels when
   monthly is picked. Yearly is also the checked default, which is what
   actually moves the annual/monthly split — see plans.du. */
#cycle-monthly:checked ~ .cycle-row .cycle-thumb {
    transform: translateX(100%);
}

/* flex-basis 0 so both halves are the width of the wider word rather than
   of their own text, which is what keeps the thumb aligned. */
.cycle-option {
    position: relative;
    z-index: 1;
    flex: 1 1 0;
    /* Wide enough for the longer of the two labels plus air on both
       sides. flex-basis 0 keeps the halves equal whatever they say, which
       is what keeps the thumb aligned under them. */
    min-width: 9.5rem;
    padding: 0.6rem 1.5rem;
    white-space: nowrap;
    text-align: center;
    font-size: var(--text-base);
    font-weight: 600;
    color: var(--text-secondary);
    cursor: pointer;
    /* Color only — the thumb behind it is what moves. */
    transition: color 0.2s;
    user-select: none;
}

.cycle-option:hover {
    color: var(--text-primary);
}

#cycle-monthly:checked ~ .cycle-row .cycle-option[for="cycle-monthly"],
#cycle-annual:checked ~ .cycle-row .cycle-option[for="cycle-annual"] {
    color: #fff;
}

.cycle-note {
    text-align: center;
    font-size: var(--text-base);
    color: var(--text-muted);
}

/* WHICH CYCLE IS SHOWING.

   Every card carries both prices, both notes and both buy links. Exactly
   one radio is checked, so exactly one of these two rules is live and it
   hides the cycle you are not on. Hiding only — nothing here has to give
   an element its display back, which is what stops .btn coming back as
   plain inline text. */
#cycle-monthly:checked ~ .cycle-row .on-annual,
#cycle-monthly:checked ~ .plans .on-annual,
#cycle-monthly:checked ~ .plan-wide .on-annual,
#cycle-annual:checked ~ .cycle-row .on-monthly,
#cycle-annual:checked ~ .plans .on-monthly,
#cycle-annual:checked ~ .plan-wide .on-monthly {
    display: none;
}

/* The priced pair, two across and never more. Commerce and Enterprise
   take the full measure underneath as .plan-wide, so this grid only ever
   holds two cards — stated as two tracks rather than left to auto-fit,
   because two is the design and not an arithmetic coincidence. */
.plans {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1.5rem;
    margin-top: 2rem;
}

.plan {
    background-color: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--bubble-radius);
    padding: 2rem;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.plan-featured {
    border-color: var(--primary);
}

/* THE FREE ROW — above the priced cards, and deliberately not one of them.

   Slimmer than a card and the full measure wide, so it reads as the way
   in rather than the cheapest rung: a reader scanning cards compares
   prices, and a free one wins that comparison without telling them
   anything. Dashed, because it is the only offer on the page that is not
   a purchase. */
.plan-strip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem 2rem;
    background-color: var(--card-bg);
    border: 1px solid var(--border);
    border-radius: var(--bubble-radius);
    padding: 1.5rem 2rem;
    /* Clear of the cycle note above it, which is small type and sits close
       to its switch — without this the row reads as part of that control
       rather than as the first thing being offered. */
    margin: 2rem 0 1.5rem;
}

.plan-strip-text {
    /* Beside a button that must not shrink. */
    flex: 1 1 22rem;
    min-width: 0;
    /* Name and line on one row, sharing a baseline: two short phrases, and
       stacking them made a two-line block out of a sentence. Wraps on a
       narrow screen, where they do become two lines. */
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.1rem 0.75rem;
}

/* The heading and the grey line under it are the cards' own — same
   elements, same rules — so the row reads as part of the set rather than
   as a banner that wandered in. Only the card's stacking margins come
   off: this is one line above another, not a column of blocks. */
.plan-strip h3 {
    margin: 0;
}

/* The card's margins are for a column. On one row they are nothing but a
   nudge out of alignment. */
.plan-strip .plan-who {
    margin: 0;
}

/* ENTERPRISE — full width under the pair, two columns.

   Its own shape because it is a different kind of offer: the other two are
   a price and a button, this one is the start of a conversation. What you
   get is on the left, where the eye starts and where the narrow cards put
   their lists; the sentence and the button that answer it sit right. */
.plan-wide {
    /* Its own element after .plans, not a third item inside it. In the
       grid it kept the third auto-fit track alive — the track it spanned
       could not collapse — and the two priced cards were squeezed into a
       third of the measure each to make room for a column nothing sat in. */
    margin-top: 1.5rem;
    display: block;
}

/* The name and the price get a row to themselves across the full width,
   the way the narrow cards lead with theirs — then the two columns start
   under a line that has already said what this is.

   Flex with .plan's own gap, and not for layout: .plan is a flex column
   and .plan-wide turns that back off (see the note above), so a head left
   as a plain block loses the 0.75rem between every line the narrow cards
   get for free. The name, the subtitle and the price then sit on their
   own margins alone — which for .plan-who is a *negative* top margin
   tuned to be eaten by that gap, so the subtitle rides up into the name.
   Same declaration here, same rhythm in both kinds of card. */
.plan-wide-head {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin-bottom: 1.75rem;
}

.plan-wide-body {
    display: grid;
    /* The list is the wider of the two — it is lines of text, and the
       column beside it is one sentence and a button. */
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    gap: 1.5rem 3.5rem;
    align-items: start;
}

.plan-wide-lead {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
}

.plan-wide .plan-list {
    margin: 0;
}

/* The free row's heading is the same heading, so it is the same rule —
   sharing the selector rather than restating the values, which is how the
   two drift apart. */
.plan h3,
.plan-strip h3 {
    font-size: var(--text-lg);
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--text-primary);
}

/* WHO THE TIER IS FOR — the line that does the actual sorting.

   Tight under the name and set quiet, because it is an aside to the
   heading rather than a line of its own: the reader is scanning names,
   finds one, and this is what confirms it. Pulled up against the h3 and
   given the air underneath, so it reads as part of the title block and
   not as the first thing about the price. */
.plan-who {
    margin-top: -0.35rem;
    margin-bottom: 0.35rem;
    font-size: var(--text-base);
    line-height: 1.45;
    color: var(--text-muted);
}

.plan-price {
    font-size: var(--text-2xl);
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1;
    color: var(--text-primary);
}

/* Small and raised toward the cap height of the digits beside it, so the
   number is what carries the line. em throughout, so it tracks whatever
   size .plan-price is set to. */
.plan-currency {
    font-size: 0.5em;
    vertical-align: 0.62em;
    letter-spacing: 0;
    margin-right: 0.04em;
}

.plan-price .plan-per {
    /* A class, not `.plan-price span`: each price is now wrapped in a span
       of its own for the switch above, and that selector styled the
       wrapper as well as the unit inside it. */
    display: inline;
    margin-left: 0.35rem;
    font-size: var(--text-base);
    font-weight: 500;
    letter-spacing: 0;
    color: var(--text-muted);
}

.plan-list {
    list-style: none;
    display: grid;
    gap: 0.4rem;
    font-size: var(--text-base);
    color: var(--text-secondary);
    margin: 0.5rem 0 1rem;
}

/* The arrow gets a column of its own, so a line that wraps stays under
   its own first word instead of tucking beneath the mark. */
.plan-list li {
    display: grid;
    grid-template-columns: 1.4rem minmax(0, 1fr);
    align-items: start;
}

.plan-list li::before {
    content: "→";
    color: var(--primary);
}

/* A button that is the whole of a band's full-width block — the home
   page's one CTA — centers on the measure. Scoped to a direct child so it
   can't reach a .btn inside the widget, the steps or the plans. */
.band-full > .btn {
    display: block;
    width: fit-content;
    margin-inline: auto;
}

/* Two of them, centered as a pair, wrapping onto their own lines when the
   measure runs out rather than shrinking the words. The step above is
   its own: .band-full's margin is set for a block that continues the
   copy, and a pair of buttons is the end of it. */
.btn-row {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 1rem;
    margin-top: 1.5rem;
}

/* Left, on the card's own left edge: everything above it in the card —
   the name, the subtitle, the price, every line of the list — starts
   there, and a centered button is the one thing that doesn't. margin-top
   is what still pushes it to the bottom, so the cards' buttons line up
   with each other however long their lists are. */
.plan .btn {
    margin-top: auto;
    align-self: flex-start;
}

/* The wide card is display:block, so its button is laid out by
   .plan-wide-lead instead — same left edge, but no card bottom to push it
   down to.

   A narrow card's button sits 1.75rem below the list: the card's own
   0.75rem gap, plus the 1rem .plan-list carries under itself. The lead
   column gives the first of those; this is the second, so the step above
   a button is the same in both kinds of card, in both layouts. Change
   .plan-list's bottom margin and change this with it. */
.plan-wide-lead > .btn {
    margin-top: 1rem;
}

/* A plan you can't buy yet: the CTA's slot, without a button in it. */
.plan-soon {
    margin-top: auto;
    align-self: flex-start;
    padding: 0.75rem 0;
    font-size: var(--text-base);
    font-weight: 600;
    color: var(--text-muted);
}

.plans-note {
    max-width: 38rem;
    margin: 1.75rem auto 0;
    text-align: center;
    font-size: var(--text-base);
    color: var(--text-muted);
}

.plans-note a {
    color: var(--complement);
    text-decoration: underline;
    text-underline-offset: 0.15rem;
}

.plans-note a:hover {
    color: var(--text-primary);
}

/* FAQ — <details> so it opens with no script at all. */

/* Full width, unlike the other blocks that sit in a .band-full. Each row
   is a ruled line with the +/- pushed to its right end, so stopping the
   list short of the measure leaves every one of those rules ending in
   mid-air against nothing. The answer below is capped instead — see
   .faq details p — which is where the readable measure actually
   mattered. */
.faq {
    margin-top: 2rem;
}

.faq details {
    border-bottom: 1px solid var(--border);
    padding: 1rem 0;
}

.faq summary {
    cursor: pointer;
    font-size: var(--text-md);
    font-weight: 600;
    color: var(--text-primary);
    list-style: none;
    display: flex;
    justify-content: space-between;
    gap: 1rem;
}

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

.faq summary::after {
    content: "+";
    color: var(--primary);
    font-weight: 400;
}

.faq details[open] summary::after {
    content: "–";
}

.faq details p {
    /* The rules above and below run the full measure; the prose does not.
       Same 38rem the legal pages and the flat bands use. */
    max-width: 38rem;
    margin-top: 0.75rem;
    color: var(--text-secondary);
    font-size: var(--text-base);
}

/* BUTTONS — same treatment as the dashboard. */

.btn {
    display: inline-block;
    align-self: flex-start;
    padding: 0.75rem 1.75rem;
    border: 1px solid transparent;
    border-radius: var(--pill-radius);
    font-family: inherit;
    font-size: var(--text-base);
    font-weight: 600;
    cursor: pointer;
    transition: filter 0.15s, background-color 0.2s, box-shadow 0.15s;
}

.btn-primary {
    background-color: var(--primary);
    color: white;
}

.btn-primary:hover {
    color: white;
    filter: brightness(var(--hover-brightness));
    box-shadow: 0 0.25rem 0.75rem var(--shadow-color);
}

/* The outline button: the primary's edge, body text inside it. Purple on
   purple reads as a second ask; this reads as the way out of one. */
.btn-secondary {
    background-color: transparent;
    border-color: var(--primary);
    color: var(--text-secondary);
}

.btn-secondary:hover {
    background-color: color-mix(in srgb, var(--primary) 14%, transparent);
    color: var(--text-primary);
}

/* RESPONSIVE

   Three breakpoints, each responsible for exactly one shape change, and
   they do not overlap. Everything else scales fluidly with clamp(), so
   nothing between them steps.

     640px — the cards give up their columns: the priced pair runs single
             file, and the wide cards' two halves stack.
     480px — the nav links collapse behind the burger.
     320px — the bands drop their two-column stagger and run single file.

   Below 480 the page is a burger nav over staggered content. The stagger
   holds down to 320 because it is the page's character, and two narrow
   columns still read better than the alternative of giving it up the
   moment the nav does.

   The cards go first, and higher, because they are where columns are set
   inside a card rather than across the measure: a card is already paying
   its own padding on both sides, so its columns run out of room well
   before anything else on the page does.

   (The file this replaced had three blocks — 600px, then 960px, then
   600px again — with the 960px block sandwiched between the two 600px
   ones, so it won the cascade on every property they shared. Keep these
   ordered widest-first and non-overlapping and that can't recur.) */

/* The cards give up their columns: the priced pair runs single file, and
   inside each wide card the bullet list drops under the ask rather than
   beside it. Everything else on the page still has room at this width —
   see the note above about why the cards run out first.

   Both are the same failure and so they share a breakpoint: a grid of
   columns set *inside* a card is already paying the card's padding twice
   over, so it runs out of measure well before the page does. */

@media (max-width: 640px) {
    .plans {
        grid-template-columns: minmax(0, 1fr);
    }

    /* One column, in the DOM's order: list, then the sentence and the
       button. Same order the narrow cards stack in, which is the point of
       the list being first. */
    .plan-wide-body {
        grid-template-columns: minmax(0, 1fr);
        gap: 1.75rem;
        align-items: start;
    }

    /* The free row's name and line share a baseline where there is room
       for them. There isn't here: the line wraps to two of its own, and a
       name with a wrapped sentence trailing off its right shoulder reads
       as neither a heading nor a paragraph. Stacked, it is the heading
       and subtitle every card above it has. */
    .plan-strip-text {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.25rem;
    }

    /* BENEFITS — the card gives up its two columns with the grid: a mark
       on its own row, the words under it. Beside a 2.75rem mark the body
       was a column of three-word lines with a card's padding either side
       of it, which is what made a wide card look wrong the moment it went
       narrow. The mark keeps its size and the left edge the heading and
       the body sit on; only the column it had beside them is gone. */
    .benefit {
        grid-template-columns: minmax(0, 1fr);
    }

    .benefit-icon {
        grid-row: auto;
        justify-self: start;
        margin-bottom: 0.75rem;
    }

    .benefit h3,
    .benefit p {
        grid-column: 1;
    }

    /* And once it is stacked it is a card, so it is padded like one: the
       1.5rem is for a slim row, and against .plan's 2rem it reads as a
       button sitting low in its bubble. The row gap is the cards' step
       above a button for the same reason. */
    .plan-strip {
        padding: 2rem;
        row-gap: 1.75rem;
    }
}

@media (max-width: 640px) {
    .nav {
        /* What separates the four things on the bar, and the size of a
           mark in the menu — a step under the burger's bars, which are
           what the marks line up with. */
        --bar-gap: 0.4rem;
        --menu-icon: 1.25rem;
    }

    /* NAV — the burger takes the row's place. .nav-links leaves the flex
       line and becomes a panel under the bar, shown only when the
       checkbox is checked.
       Burger first, wordmark beside it, menu left-aligned under both —
       the same shape as the dashboard's. */

    .nav-burger {
        display: flex;
        order: 1;
        /* Pull the bars back to the bar's left edge; the padding is hit
           area, and without this the burger floats in from the gutter. */
        margin-left: calc(-1 * var(--burger-pad));
    }

    .brand {
        order: 2;
    }

    /* The one tap worth having without opening anything. */
    .nav-mobile-actions {
        display: flex;
        align-items: center;
        order: 3;
    }

    .nav-mobile-actions a.nav-cta {
        padding: 0.45rem 0.9rem;
        border-radius: var(--pill-radius);
        background-color: var(--primary);
        color: #fff;
        font-size: var(--text-base);
        font-weight: 500;
        white-space: nowrap;
    }

    /* Smaller than the bar above the breakpoint: the burger and the pill
       are fixed-size, and the wordmark is what gives back the room they
       need. It is a flat width and not a clamp because the burger, the
       wordmark and one pill fit the narrowest phone with room to spare —
       put a second link back on this bar and that stops being true. */
    .brand-img {
        width: 5.5rem;
    }

    .nav-links {
        display: none;
        /* Last, so the sheet wraps onto its own line under the whole bar
           and the toggle stays up on it. */
        order: 4;
        width: 100%;
    }

    .nav-state:checked ~ .nav-links {
        display: block;
    }

    .nav-inner {
        flex-wrap: wrap;
        gap: var(--bar-gap);
    }

    .nav-links ul {
        flex-direction: column;
        /* Stretch, not flex-start: the row is the touch target, so it
           runs the width of the sheet even though the label sits left. */
        align-items: stretch;
        gap: 0;
        padding-top: 0.5rem;
    }

    /* Every row in the sheet is the same two columns, and the bar above
       sets both of them: the first is the burger's bars, so a mark sits
       centered on the burger; the gap after it is the rest of the way to
       the wordmark — the burger's own padding, plus the gap the wordmark
       sits after on the bar. Change the burger and the menu follows. */
    .nav-links a,
    .nav-theme .theme-toggle {
        /* A touch target, not a link in a list: the row is the hit area,
           and the padding runs out to the right of the label so the whole
           width of the sheet is tappable. */
        min-height: 2.6rem;
        display: grid;
        grid-template-columns: calc(var(--burger-size) - 2 * var(--burger-pad)) 1fr;
        column-gap: calc(var(--burger-pad) + var(--bar-gap));
        align-items: center;
        padding: 0.35rem 2rem 0.35rem 0;
        font-size: var(--text-lg);
        font-weight: 700;
    }

    /* Smaller than the bars it sits under: a mark is what the eye lands
       on before the word, not a second thing to read. One size for every
       row, the theme toggle's included — the minor rows are lighter, not
       smaller. */
    .nav-icon,
    .nav-theme .theme-icon {
        /* The base rule hides both — this is the width that shows them. */
        display: block;
        justify-self: center;
        width: var(--menu-icon);
        height: var(--menu-icon);
        color: inherit;
    }

    /* The sheet's copy of the CTA goes: the pill is on the bar above it,
       on screen the whole time the menu is open, and the same ask twice
       in view is a menu arguing with itself. */
    .nav-links .nav-cta {
        display: none;
    }

    /* Present, but not competing with the rows above: same size and
       spacing, normal weight, muted. */
    .nav-minor {
        display: list-item;
    }

    /* Weight is what sets these apart from the three above, not color —
       every link on the site is the same blue now. */
    .nav-links a.nav-minor {
        font-weight: 400;
    }

    .nav-links a.nav-minor:hover {
        color: var(--text-primary);
        text-decoration: underline;
    }

    .nav-links a.nav-minor[aria-current="page"] {
        color: var(--text-primary);
    }

    /* Last row of the sheet: it is a setting rather than a destination,
       so it sits at the bottom, in the minor links' weight, and names the
       mode beside the icon — theme.js writes the word in. */
    .nav-theme {
        display: list-item;
    }

    .nav-theme .theme-toggle {
        width: 100%;
        /* A button centers its text; every row above it starts left. */
        text-align: left;
        font-weight: 400;
        color: var(--complement);
    }

    .nav-theme .theme-toggle:hover {
        color: var(--text-primary);
    }

    /* FOOTER — the two columns stack; the links keep flowing. */
    .foot-inner {
        grid-template-columns: minmax(0, 1fr);
    }

    /* Burger -> X. The middle bar goes, the outer two cross. */
    .nav-state:checked + .nav-burger span:nth-child(1) {
        transform: translateY(7px) rotate(45deg);
    }

    .nav-state:checked + .nav-burger span:nth-child(2) {
        opacity: 0;
    }

    .nav-state:checked + .nav-burger span:nth-child(3) {
        transform: translateY(-7px) rotate(-45deg);
    }

}

/* One column, headline left-aligned: a right-aligned headline over a
   full-width column reads as a mistake rather than a choice. The stagger
   is the page's whole character, so it is held to the last width where
   two columns still fit rather than dropped with the nav at 480. */

@media (max-width: 320px) {
    .band {
        grid-template-columns: minmax(0, 1fr);
        max-width: 44rem;
        margin-bottom: 3rem;
    }

    .band-title {
        grid-column: 1;
        grid-row: 1;
        text-align: left;
    }

    /* Headline left, supporting copy right. Stacked, the two columns are
       gone but the diagonal they made can still be read off the ragged
       edges — the stagger survives the loss of the grid. */
    .band-body {
        grid-column: 1;
        grid-row: 2;
        text-align: right;
    }

}

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