/* repconnect — landing fixes + onboarding / offers board / billing components.
   built on the tokens in main.css: no new fonts; the only new colours are the
   hero crescent tints, which live in static/js/pages/home.mjs. */

/* ---------------------------------------------------------------- fixes */

/* main.css sets body{overflow:hidden}, which makes body a scroll container.
   the absolutely positioned .gradient-container boxes give it ~445px of
   scrollable overflow, so a #fragment jump scrolls body internally and the
   wheel cannot put it back. clip clips the same way without scrolling. */
body { overflow: clip; }

/* lenis (common.mjs) eases the wheel; an iframe under the cursor (stripe elements)
   would swallow the wheel mid-ease and stall it. */
.lenis.lenis-smooth iframe { pointer-events: none; }

/* .card sets display:flex, which beats the ua sheet's [hidden]{display:none} */
[hidden] { display: none !important; }

/* keeps a hyphenated word whole; DM Sans has no non-breaking hyphen (U+2011) */
.nowrap { white-space: nowrap; }

/* ---------------------------------------------------------------- hero */

/* full-viewport hero: copy left, the board right, crescent canvas behind both.
   section.hero:before (main.css) is the bottom fade at z-index 1: content
   sits above it, the canvas below, so the dither fades into the page. */
section.hero {
    min-height: 100svh;
    padding-top: var(--header-height);
    align-items: center;
}
section.hero .hero-dither {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    image-rendering: pixelated;
    pointer-events: none;
}
section.hero .section-content {
    z-index: 2;
    flex-direction: row;
    justify-content: space-between;
    /* 48px across buys the headline's second line room for 52px; stacked
       layouts keep the 64px row gap. */
    gap: var(--padding-medium) 48px;
    padding: var(--padding-medium) 0;
}
section.hero .hero-copy {
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--padding-small);
    /* centered against the board, then lifted 16px (half this margin) */
    margin-bottom: 32px;
    --headline-size: clamp(38px, 3.6vw, 50px);
}
/* sized so the headline holds two lines in the copy column; the longer
   second line sets the cap. the mark above it is the header's, cropped to its
   glyph and scaled off the headline so the two keep their proportion on every
   screen. */
section.hero .hero-copy h1 { margin-bottom: calc(20px - var(--padding-small)); font-size: calc(var(--headline-size) + 2px); letter-spacing: -3px; }
section.hero .hero-copy h1 .lead { font-size: calc(var(--headline-size) + 4px); }
section.hero .hero-copy .hero-logo { width: calc(var(--headline-size) * 2.38); height: auto; }
section.hero .hero-copy p { max-width: 560px; font-size: 22px; }
section.hero .actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 8px; }
section.hero .actions .button { height: 52px; padding: 0 28px; font-size: 19px; }
@media only screen and (max-width: 1024px) {
    section.hero .section-content { flex-direction: column; justify-content: center; }
    section.hero .hero-copy { align-items: center; margin-bottom: 0; text-align: center; }
    section.hero .actions { justify-content: center; }
}
@media only screen and (max-width: 768px) {
    section.hero .hero-copy h1 { letter-spacing: -1px; }
    section.hero .hero-copy p { display: none; }
}

/* the hero's product shot. the cards are the live board's .offer parts; the
   whole board sits on one glass panel so its headings stay readable over the
   crescent, not just the cards. */
.hero-board { flex: 0 0 460px; max-width: 100%; }
.hero-board .preview {
    -webkit-backdrop-filter: blur(24px);
    gap: 12px;
    padding: 16px;
    border-radius: var(--border-radius-large);
    backdrop-filter: blur(24px);
    background-color: color-mix(in srgb, var(--color-background-primary) 75%, transparent);
}
/* .card.offer sits later in this file, so the hero override carries the extra class */
.hero-board .card.offer { flex: none; padding: 16px 20px; }
@media only screen and (max-width: 1024px) { .hero-board { flex-basis: auto; width: 100%; max-width: 512px; } }

/* ---------------------------------------------------------------- landing sections */

/* the captured design spaces sections 192px apart; at this page's length that
   reads as empty screens between the points. */
.home section.content { margin-bottom: var(--padding-large); }
.home section.content .card .nummeration { align-self: flex-start; }
/* anchor jumps land below the fixed header; main.css only leaves 5ex on
   :target, which put each label under it and which lenis never sees: it aims
   before the hash changes. 64px is header.small, the height once scrolled. */
.home section[id], #plans { scroll-margin-top: 64px; }

.compare { width: 100%; border-collapse: collapse; font-size: 16px; text-align: left; }
.compare th, .compare td { padding: 14px 16px; border-top: 1px solid var(--color-background-elevation); vertical-align: top; }
.compare thead th { border-top: none; color: var(--color-secondary); font-weight: 500; font-size: 14px; }
.compare thead th.us { color: var(--green); }
.compare tbody th { font-weight: 500; }
.compare td { color: var(--color-secondary); }
.compare td.us { color: var(--color-primary); }
/* phones: each row becomes the label over its two answers */
@media only screen and (max-width: 640px) {
    .compare thead { display: none; }
    .compare tr { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 16px; padding: 14px 0; border-top: 1px solid var(--color-background-elevation); }
    .compare tr:first-child { border-top: none; }
    .compare th, .compare td { padding: 0; border: none; }
    .compare tbody th { grid-column: span 2; }
    .compare td::before { content: attr(data-label); display: block; color: var(--color-secondary); font-size: 12px; }
    .compare td.us::before { color: var(--green); }
}

/* the outreach radar (static/js/radar.mjs), section 2's illustration. the
   canvas draws the field; corners, tags and the hub mark sit over it in css
   px. a card is at most 440px wide; .wide takes the section's 1200 x 530 box
   above 1024px (radar left, text right) and below it is a card of at most
   512px, as the bento's cards are. the marketing radar pages share these rules. */
.card.radar { width: 100%; max-width: 440px; gap: 16px; padding: 20px; border: 1px solid var(--color-background-elevation); }
.radar-head { display: flex; align-items: center; gap: 12px; }
.radar-icon { display: grid; flex: none; place-items: center; width: 36px; height: 36px; border-radius: var(--border-radius-small); background-color: var(--color-background-elevation); }
.radar-icon svg { width: 20px; height: 20px; }
.radar-title { display: flex; flex: 1; flex-direction: column; min-width: 0; line-height: 1.35; }
.radar-scope { position: relative; aspect-ratio: 1; }
.radar-scope canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.radar-corner { position: absolute; font-size: 14px; }
.radar-tag { position: absolute; top: 0; left: 0; opacity: 0; pointer-events: none; }
.radar-avatar {
    position: absolute; top: -14px; left: -14px; display: grid; place-items: center; width: 28px; height: 28px;
    border: 1.5px solid var(--tone); border-radius: 50%;
    background-color: color-mix(in srgb, var(--tone) 28%, var(--color-background-primary)); font-weight: 500; font-size: 11px;
}
.radar-label {
    position: absolute; bottom: 20px; left: 0; padding: 2px 8px;
    border: 1px solid color-mix(in srgb, var(--color-primary) 12%, transparent); border-radius: var(--border-radius-small);
    background-color: color-mix(in srgb, var(--color-primary) 6%, var(--color-background-primary));
    font-size: 13px; white-space: nowrap; transform: translateX(-50%);
}
.radar-tag.below .radar-label { top: 20px; bottom: auto; }
.radar-label b { margin-left: 6px; color: var(--tone); }
.radar-label b, .radar-legend b, .radar-count, .radar-feed small { font-weight: 400; font-family: "DM Mono", monospace; }
.radar-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background-color: var(--tone); }
.radar-legend { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 24px; margin: 0; padding: 0; list-style: none; }
.radar-legend li { display: flex; align-items: center; gap: 8px; color: var(--color-secondary); font-size: 14px; }
.radar-legend b { margin-left: auto; color: var(--color-primary); font-size: 14px; }
.radar-legend .radar-note { justify-content: flex-end; }
.radar-panel {
    display: flex; flex-direction: column; gap: 10px; padding: 14px 16px;
    border: 1px solid var(--color-background-elevation); border-radius: var(--border-radius-medium); background-color: var(--color-background-primary);
}
.radar-status { display: flex; align-items: center; gap: 10px; font-size: 14px; white-space: nowrap; }
/* one cell per source, stacked so the crossfade never moves the row; a
   source's logo, when it has one, stands in for its name */
.radar-swap { display: grid; }
.radar-swap > * { grid-area: 1 / 1; }
.radar-swap svg { display: block; width: 16px; height: 16px; }
.radar-bar { display: flex; flex: 1; gap: 3px; min-width: 48px; }
.radar-bar i { flex: 1; height: 4px; overflow: hidden; border-radius: 2px; background-color: var(--color-background-elevation); }
.radar-bar b { display: block; height: 100%; background-color: var(--green); transform: scaleX(0); transform-origin: left; }
/* wide enough for "7,200 → 53", so the bar beside it doesn't shift as digits are added */
.radar-count { min-width: 10ch; color: var(--color-secondary); font-size: 13px; text-align: right; }
.radar-feed { position: relative; height: 90px; margin: 0; padding: 0; overflow: hidden; list-style: none; }
.radar-feed li {
    position: absolute; top: 0; right: 0; left: 0; display: flex; align-items: center; gap: 10px; height: 30px;
    color: var(--color-secondary); font-size: 14px; opacity: 0;
}
.radar-feed span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.radar-feed span b { color: var(--color-primary); font-weight: 500; }
.radar-feed small { flex: none; margin-left: auto; font-size: 13px; }
.card.radar.wide { max-width: 512px; }
/* a phone-width card (358px on a 390px screen) has no room for the scanned → kept counts */
@media only screen and (max-width: 480px) {
    .radar-count { display: none; }
}
/* two 249px bento rows and their 32px gap make the 530px box: the scope is
   that height less a 24px inset, and the text column starts 48px in */
@media only screen and (min-width: 1025px) {
    .card.radar.wide {
        display: grid; grid-template-rows: auto auto minmax(0, 1fr); grid-template-columns: 482px minmax(0, 1fr);
        gap: 24px 48px; max-width: none; height: 530px; padding: 24px 48px 24px 24px;
    }
    .radar.wide .radar-scope { grid-row: 1 / -1; }
    .radar.wide .radar-head { padding-top: 24px; }
    .radar.wide .radar-title strong { font-size: 28px; line-height: 1.25; }
    .radar.wide .radar-title small { font-size: 18px; }
    .radar.wide .radar-feed { flex: 1; height: auto; }
    .radar.wide .radar-legend li, .radar.wide .radar-legend b { font-size: 16px; }
    .radar.wide .radar-status, .radar.wide .radar-feed li { font-size: 15px; }
}

/* .final: the card the site ships (mountFinal). its headline block, with the
   scanned → kept tally in large type, takes the head's and legend's place */
.radar.final .radar-head, .radar.final .radar-legend { display: none; }
.radar-intro-title { display: flex; align-items: center; gap: 12px; margin-bottom: 6px; }
.radar-intro h3 { margin: 0; font-size: 27px; line-height: 1.15; letter-spacing: -.035em; }
.radar-intro p { margin: 0; color: var(--color-secondary); font-size: 13px; }
.radar-intro-counts { display: grid; grid-template-columns: 1fr auto 1fr; align-items: end; gap: 18px; margin-top: 12px; }
.radar-intro-counts strong { min-width: 0; font-family: "DM Mono", monospace; font-size: clamp(31px, 3.25vw, 48px); line-height: 1; letter-spacing: -.075em; }
.radar-intro-counts strong:last-child { color: var(--green); }
.radar-intro-counts span { padding-bottom: 3px; color: color-mix(in srgb, var(--green) 55%, transparent); font-size: 23px; }
.radar-intro-labels {
    display: grid; grid-template-columns: 1fr 1fr; gap: 40px; margin-top: 6px;
    color: var(--color-secondary); font-family: "DM Mono", monospace; font-size: 9px; letter-spacing: .09em; text-transform: uppercase;
}
@media only screen and (min-width: 1025px) {
    /* the scope takes the card's whole inner height (528px inside its 1px
       border) instead of the 24px inset, and --radar-frame has the engine
       stretch the 482px radar 9.5% to fill it; the radar's own margin (23px
       to its ticks) stands in for the inset */
    .card.radar.wide.final { --radar-frame: 482; grid-template-columns: 528px minmax(0, 1fr); padding: 0 48px 0 0; }
    /* the brackets frame the radar's ticks, clear of the card's 24px corner radius */
    .radar.final.wide .radar-scope::after { inset: 16px; }
    /* the intro fills the head's and legend's grid rows; the panel keeps the last, stretching one */
    .radar.wide .radar-intro { grid-row: span 2; padding-top: 48px; }
    .radar.final.wide .radar-panel { margin-bottom: 24px; }
}
@media only screen and (max-width: 1024px) {
    .radar-intro-counts strong { font-size: clamp(32px, 8vw, 48px); }
}
@media only screen and (max-width: 480px) {
    .radar-intro h3 { font-size: 23px; }
    .radar-intro-counts { gap: 10px; }
}
/* the outline: a 2px conic ring masked to the border, turned by --orbit. it
   sits over the card's own 1px border (inset -1px), so its peaks read 2px,
   not border plus ring, and its corners keep the card's radius */
.card.radar.final { position: relative; isolation: isolate; border-color: color-mix(in srgb, var(--green) 25%, var(--color-background-elevation)); }
.radar.final::before {
    position: absolute; z-index: 2; inset: -1px; padding: 2px; border-radius: inherit;
    background: conic-gradient(from var(--orbit, 0deg), transparent 0 23%, color-mix(in srgb, var(--green) 95%, white) 32%, transparent 43% 72%, color-mix(in srgb, var(--green) 70%, transparent) 82%, transparent 93%);
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask-composite: exclude;
    pointer-events: none; content: "";
}
/* corner brackets on the scope, breathing with --bracket */
.radar.final .radar-scope::after {
    position: absolute; z-index: 1; inset: 8px; opacity: var(--bracket, .7);
    background:
        linear-gradient(var(--green) 0 0) left top / 18px 1px no-repeat,
        linear-gradient(var(--green) 0 0) left top / 1px 18px no-repeat,
        linear-gradient(var(--green) 0 0) right top / 18px 1px no-repeat,
        linear-gradient(var(--green) 0 0) right top / 1px 18px no-repeat,
        linear-gradient(var(--green) 0 0) left bottom / 18px 1px no-repeat,
        linear-gradient(var(--green) 0 0) left bottom / 1px 18px no-repeat,
        linear-gradient(var(--green) 0 0) right bottom / 18px 1px no-repeat,
        linear-gradient(var(--green) 0 0) right bottom / 1px 18px no-repeat;
    pointer-events: none; content: "";
}
/* a locked tag: the avatar glows and the label takes its tone */
.radar.final .radar-label {
    border-color: color-mix(in srgb, var(--tone) 35%, transparent);
    background-color: color-mix(in srgb, var(--tone) 8%, var(--color-background-primary));
}
.radar.final .radar-avatar { box-shadow: 0 0 12px color-mix(in srgb, var(--tone) 35%, transparent); }
/* the feed fits whole 30px rows and leaves the rest (--feed-spare, from the
   engine) below the last one: shift the status row and feed down by half of
   it, so the panel's top and bottom gaps match. the 3px is a feed row's text
   sitting that much higher in its row than the status text sits in its line */
.radar.final .radar-status, .radar.final .radar-feed { transform: translateY(calc((var(--feed-spare, 0px) + 3px) / 2)); }

.plan .for { color: var(--green); font-weight: 500; font-size: 14px; letter-spacing: 2px; text-transform: uppercase; }

/* ---------------------------------------------------------------- layout */

section.page {
    padding-top: calc(var(--header-height) + var(--padding-medium));
    margin-bottom: var(--padding-large);
}

section.page .section-content {
    align-items: stretch;
    gap: var(--padding-small);
}

.stack { display: flex; flex-direction: column; gap: var(--padding-small); }
.stack.tight { gap: var(--padding-extra-small); }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.centered { align-items: center; text-align: center; }

.breadcrumb { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--color-secondary); }
.breadcrumb a { font-weight: 400; color: var(--color-secondary); }
.breadcrumb a:hover { color: var(--color-primary); }
.breadcrumb strong { color: var(--color-primary); }
.breadcrumb svg { width: 14px; height: 14px; opacity: .5; }

.pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    border-radius: 10px;
    background-color: var(--color-background-elevation);
    font-size: 12px;
    font-weight: 500;
}
.pill.green { background-color: var(--green); color: var(--black); }
.pill.red { background-color: var(--red); color: var(--black); }

/* ---------------------------------------------------------------- forms */

.field { display: flex; flex-direction: column; gap: 10px; }
.field > .label { font-weight: 500; font-size: 18px; }
.field > .hint { font-size: 14px; color: var(--color-secondary); }

.input {
    width: 100%;
    height: 48px;
    padding: 0 16px;
    border: 1px solid transparent;
    border-radius: var(--border-radius-medium);
    background-color: var(--color-background-elevation);
    color: var(--color-primary);
    font-size: 16px;
}
.input::placeholder { color: var(--color-secondary); }
.input:focus { border-color: var(--green); }
.input:-webkit-autofill,
.input:-webkit-autofill:focus {
    -webkit-text-fill-color: var(--color-primary);
    -webkit-box-shadow: 0 0 0 1000px var(--color-background-secondary) inset;
}

.choices { display: flex; flex-wrap: wrap; gap: 8px; }
.choice { position: relative; display: inline-flex; }
.choice input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.choice span {
    display: inline-flex;
    align-items: center;
    height: 40px;
    padding: 0 18px;
    border: 1px solid transparent;
    border-radius: 20px;
    background-color: var(--color-background-elevation);
    font-weight: 500;
    font-size: 16px;
    cursor: pointer;
    transition: background-color .1s ease, color .1s ease;
}
.choice input:checked + span { background-color: var(--green); color: var(--black); }
.choice input:focus-visible + span { border-color: var(--color-primary); }

.field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--padding-extra-small); }
.field-grid .span-2 { grid-column: span 2; }
@media only screen and (max-width: 512px) {
    .field-grid { grid-template-columns: 1fr; }
    .field-grid .span-2 { grid-column: span 1; }
}

.form-actions { display: flex; flex-direction: column; gap: 8px; align-items: center; margin-top: var(--padding-extra-small); }
.form-actions .button { width: 100%; max-width: 384px; }

/* ---------------------------------------------------------------- access key */

.pin-row { display: flex; align-items: center; justify-content: center; gap: 12px; flex-wrap: wrap; }
.pin { display: flex; gap: 12px; }
.pin input {
    width: 56px;
    height: 64px;
    border: 1px solid transparent;
    border-radius: var(--border-radius-medium);
    background-color: var(--color-background-elevation);
    color: var(--color-primary);
    font-family: "DM Mono", monospace;
    font-size: 28px;
    text-align: center;
    text-transform: uppercase;
}
.pin input:focus { border-color: var(--green); }
.pin.error input { border-color: var(--red); }
.pin-submit { width: 64px; height: 64px; padding: 0; }
.pin-submit svg { width: 24px; height: 24px; }
@media only screen and (max-width: 512px) {
    .pin input { width: 44px; height: 56px; font-size: 22px; }
    .pin-submit { width: 56px; height: 56px; }
}

/* ---------------------------------------------------------------- dialog */

dialog.modal {
    width: min(520px, calc(100vw - 32px));
    padding: var(--padding-small);
    border: none;
    border-radius: var(--border-radius-large);
    background-color: var(--color-background-primary);
    color: var(--color-primary);
}
dialog.modal::backdrop { backdrop-filter: blur(4px); background-color: rgba(0, 0, 0, .6); }
dialog.modal .modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
dialog.modal .close { width: 32px; height: 32px; padding: 0; border-radius: var(--border-radius-small); background-color: var(--color-background-elevation); color: var(--color-primary); }

/* ---------------------------------------------------------------- header extras */

header .header-content nav .icon-button, .dashboard .icon-button {
    display: inline-flex;
    position: relative;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    margin: 0;
    padding: 0;
    border-radius: var(--border-radius-small);
    background-color: var(--color-background-elevation);
    color: var(--color-primary);
}
header .header-content nav .icon-button svg, .dashboard .icon-button svg { width: 20px; height: 20px; }
.notif { position: relative; }
.notif-badge {
    position: absolute;
    top: -4px;
    right: -4px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    background-color: var(--red);
    color: var(--black);
    font-size: 11px;
    font-weight: 500;
    line-height: 18px;
    text-align: center;
}
.notif-panel {
    display: none;
    z-index: 20;
    position: absolute;
    top: calc(100% + 12px);
    right: 0;
    width: min(360px, calc(100vw - 32px));
    padding: var(--padding-extra-small);
    border-radius: var(--border-radius-medium);
    backdrop-filter: blur(24px);
    background-color: var(--color-background-secondary);
}
.notif-panel.open { display: block; }
.notif-panel .notif-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.notif-panel .notif-head strong { font-size: 16px; }
.notif-panel .notif-head button { height: auto; padding: 0; background: none; color: var(--color-secondary); font-size: 14px; }
.notif-panel .notif-item { display: flex; gap: 12px; padding: 10px 8px; border-radius: var(--border-radius-small); }
.notif-panel .notif-item:hover { background-color: var(--color-background-elevation); }
.notif-panel .notif-item .dot { width: 8px; height: 8px; margin-top: 7px; border-radius: 4px; background-color: var(--green); flex: none; }
.notif-panel .notif-item.read .dot { background-color: var(--color-secondary); opacity: .4; }
.notif-panel .notif-item .text { display: flex; flex-direction: column; }
.notif-panel .notif-item .text span { font-size: 15px; }
.notif-panel .notif-foot { display: block; margin-top: 4px; padding: 10px; border-radius: var(--border-radius-small); text-align: center; font-size: 14px; }
.notif-panel .notif-foot:hover { background-color: var(--color-background-elevation); }

/* the site dropdown opens on hover; in the dashboard it is click driven */
header .header-content nav .dropdown.menu .dropdown-content.open { opacity: 1 !important; max-height: 320px !important; }

/* ---------------------------------------------------------------- dashboard */

/* the members' shell in the admin's shape: a fixed sidebar told apart by tone,
   not lines, and the board on the site's green gradient beside it. the sidebar
   is opaque so the gradient never tints it. */
.sidebar {
    display: flex;
    z-index: 10;
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    flex-direction: column;
    gap: 24px;
    width: 248px;
    padding: 24px 12px 16px;
    overflow-y: auto;
    background-color: color-mix(in srgb, var(--color-primary) 4%, var(--color-background-primary));
}
.sidebar > .logo, .topbar .logo { display: inline-flex; align-items: center; gap: 8px; font-size: 20px; }
.sidebar > .logo { padding: 0 8px; }
.nav-group { display: flex; flex-direction: column; }
.nav-group + .nav-group { margin-top: 16px; }
.nav-label { padding: 0 16px 8px; font-size: 14px; }
.sidebar .nav { display: flex; position: relative; align-items: center; gap: 8px; min-height: 36px; padding: 6px 16px; font-weight: 400; font-size: 16px; }
.sidebar .nav b { margin-left: auto; font-weight: 500; font-size: 14px; }
.sidebar .nav:hover, .sidebar .nav[aria-current=page] { opacity: 1; background-color: var(--hover-elevation); }
.sidebar .nav[aria-current=page] { font-weight: 500; }
.sidebar .nav[aria-current=page]::before { position: absolute; top: 0; bottom: 0; left: 0; width: 3px; background-color: var(--green); content: ""; }
.sidebar-foot { display: flex; align-items: center; justify-content: space-between; margin-top: auto; padding: 0 8px; font-size: 14px; }
.sidebar-foot > a { color: var(--color-secondary); font-weight: 400; }
.sidebar-foot > a:hover { opacity: 1; color: var(--color-primary); }
.theme-control { display: flex; gap: 4px; }
.theme-control input { position: absolute; width: 0; opacity: 0; }
.theme-control label { padding: 6px 12px; border-radius: 16px; color: var(--color-secondary); cursor: pointer; }
.theme-control input:checked + label { background-color: var(--hover-elevation); color: var(--color-primary); }
.theme-control input:focus-visible + label { outline: 2px solid var(--color-primary); }

/* clip keeps the 1440px gradient from making the page scroll past its content */
.dashboard { display: flex; position: relative; flex-direction: column; gap: var(--padding-small); min-height: 100vh; margin-left: 248px; padding: 32px; overflow: clip; }
.topbar { display: none; }
.page-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.page-head .count { margin-left: 8px; color: var(--color-secondary); font-weight: 400; font-size: 18px; }
.page-head p { max-width: 720px; font-size: 16px; }

/* below 769px the sidebar is a drawer under a sticky 60px topbar */
@media only screen and (max-width: 768px) {
    .sidebar { display: none; top: 60px; width: min(320px, 100%); }
    .sidebar > .logo { display: none; }
    .shell[data-menu-open=true] .sidebar { display: flex; }
    .dashboard { margin-left: 0; padding: 0 16px 32px; }
    .topbar { display: flex; z-index: 11; position: sticky; top: 0; align-items: center; gap: 12px; height: 60px; margin: 0 -16px; padding: 0 16px; background-color: var(--color-background-primary); }
}

/* ---------------------------------------------------------------- offers board */

/* on a pc, one monorail: the track scrolls natively, so a swipe and the side
   buttons drive the same scroll. phones stack the cards and the page scrolls. */
.rail { position: relative; width: 100%; }
.rail.has-nav { padding: 0 44px; }
.offers {
    display: flex;
    gap: var(--padding-small);
    overflow-x: auto;
    scroll-behavior: smooth;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
}
.offers::-webkit-scrollbar { display: none; }
/* every card is the same box: one line per field and the owner held at exactly
   two, so the height is fixed by the layout, not the data, in the rail and in
   the stack alike. the detail opens in #offerDetail instead of growing a card.
   three per view on a pc, so the next set is one page away. */
.card.offer { flex: 0 0 calc((100% - var(--padding-small) * 2) / 3); max-width: none; gap: 4px; padding: 24px; font-weight: 400; scroll-snap-align: start; }
@media only screen and (max-width: 1024px) { .card.offer { flex-basis: calc((100% - var(--padding-small)) / 2); } }
@media only screen and (max-width: 768px) {
    .offers { flex-direction: column; overflow-x: visible; scroll-snap-type: none; }
    .card.offer { flex-basis: auto; }
}

.rail-nav {
    display: flex;
    z-index: 2;
    position: absolute;
    top: calc(50% - 18px);
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border-radius: 18px;
    -webkit-backdrop-filter: blur(24px);
    backdrop-filter: blur(24px);
    background-color: var(--color-background-secondary);
    color: var(--color-primary);
}
.rail-nav.prev { left: 0; }
.rail-nav.next { right: 0; }
.rail-nav svg { width: 20px; height: 20px; }
.rail-nav[disabled] { opacity: .3; cursor: default; }

/* touch: the swipe is the affordance, the overlay buttons only get in the way */
@media (pointer: coarse) {
    .rail.has-nav { padding: 0; }
    .rail-nav { display: none; }
}
@media (prefers-reduced-motion: reduce) { .offers { scroll-behavior: auto; } }

.ote { display: flex; align-items: center; gap: 8px; font-weight: 500; font-size: 20px; letter-spacing: -.5px; white-space: nowrap; }
.offer .ote { margin-bottom: 8px; overflow: hidden; }
.offer .role { font-weight: 500; font-size: 18px; }
.offer .amount, .offer .owner { display: -webkit-box; overflow: hidden; color: var(--color-secondary); font-size: 15px; -webkit-box-orient: vertical; -webkit-line-clamp: 1; }
.offer .owner { min-height: 3em; -webkit-line-clamp: 2; }
.offer .foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: auto; padding-top: 16px; white-space: nowrap; }
.offer .foot small { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.offer .pill { flex: none; }

.offer-detail .detail { display: flex; flex-direction: column; gap: var(--padding-extra-small); margin-top: var(--padding-small); }
.offer-detail .detail p { font-size: 16px; white-space: pre-line; }
.offer-detail dl { display: grid; grid-template-columns: auto 1fr; gap: 6px 16px; margin: 0; font-size: 15px; }
.offer-detail dt { color: var(--color-secondary); }
.offer-detail dd { margin: 0; font-weight: 500; }
.offer-detail .detail .button { width: 100%; margin-top: 8px; }
.offer-detail .detail .button[disabled] { background-color: var(--color-background-elevation); color: var(--color-secondary); cursor: default; }

/* ---------------------------------------------------------------- meetings */

.meetings { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 360px), 1fr)); gap: var(--padding-small); }
.card.meeting { max-width: none; align-items: flex-start; }
.card.meeting.approved { box-shadow: inset 0 0 0 1px var(--green); }
.meeting .h3 { font-size: 20px; }
.meeting p, .meeting small { color: var(--color-secondary); }
.meeting .actions { width: 100%; margin-top: auto; flex-wrap: wrap; }
.meeting .pills { display: flex; flex-wrap: wrap; gap: 8px; }
.meeting .meeting-placeholder, .meeting .meeting-placeholder:hover { border: 1px dashed var(--color-secondary); background: transparent; color: var(--color-secondary); cursor: default; transform: none; }

/* ---------------------------------------------------------------- outreach intelligence */

/* intelligence.html: the tall radar card (radar.mjs, without the engine's
   sources pill, corner names, legend and rotating source name; the status
   row's bar takes the name's place) beside the preferences. the alert
   checkboxes are setting rows with a switch, on the phone input's surface,
   height and radius, so save is the card's only filled green control. */
.intel { display: grid; grid-template-columns: 440px minmax(0, 720px); gap: var(--padding-small); align-items: start; }
.intel .radar-head .pill, .intel .radar-corner, .intel .radar-legend, .intel .radar-swap { display: none; }
.card.intel-prefs { max-width: none; gap: 24px; padding: 20px 24px; border: 1px solid var(--color-background-elevation); }
.intel-prefs .h3 { font-size: 20px; }
.intel-prefs .choice { display: flex; }
.intel-prefs .choice span { flex: 1; justify-content: space-between; gap: 16px; height: 48px; padding: 0 16px; border-radius: var(--border-radius-medium); font-weight: 400; }
.intel-prefs .choice span::after {
    flex: none; width: 36px; height: 20px; border-radius: 10px; content: "";
    background: radial-gradient(circle at 10px 50%, var(--color-primary) 0 7px, transparent 7.5px), color-mix(in srgb, var(--color-primary) 18%, transparent);
}
.intel-prefs .choice input:checked + span { background-color: var(--color-background-elevation); color: var(--color-primary); }
.intel-prefs .choice input:checked + span::after { background: radial-gradient(circle at 26px 50%, var(--black) 0 7px, transparent 7.5px), var(--green); }
.intel-prefs .actions { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.intel-prefs .actions .button { width: 100%; }
@media only screen and (max-width: 1100px) {
    .intel { grid-template-columns: minmax(0, 720px); }
}

/* ---------------------------------------------------------------- approval */

/* the first board load after an approval plays it once (pages/board.mjs): the dialog,
   then the card. motion is the reveal's: opacity and transform, plain ease, a
   32px rise, 50ms apart. each element's own style is its last frame, so reduced
   motion starts there. */
dialog.celebrate { background-image: radial-gradient(ellipse at top, color-mix(in srgb, var(--green) 15%, transparent), transparent 70%); text-align: center; }
dialog.celebrate .close { position: absolute; top: 16px; right: 16px; }
.celebrate-copy { display: flex; flex-direction: column; align-items: center; gap: 12px; }
/* the hero's logo at the hero's size: member and owner meet, the link draws and
   the owner pulses once. */
.celebrate-copy .mark { width: 120px; height: auto; margin: 24px 0 12px; overflow: visible; }
.celebrate-copy p { color: var(--color-secondary); font-size: 16px; }
.celebrate-copy .button { width: 100%; margin-top: 12px; }
.celebrate .pulse { opacity: 0; }

/* "Job acquired" with its check inside, about 15% larger than a plain pill:
   on the card and in the dialog */
.pill.acquired { gap: 6px; height: 23px; padding: 0 8px; border-radius: 12px; font-size: 14px; }
.pill.acquired .tick { width: 5px; height: 9px; margin: 0 2px 2px 1px; border: solid currentColor; border-width: 0 2px 2px 0; transform: rotate(45deg); }

/* the card, once the dialog closes: it lifts into a green ring and wash, a
   check pops on its corner and the status lands, then it settles. the rail's
   block padding is room for the lift inside its scroll clip. */
.offers { padding-block: 12px; margin-block: -12px; }
.card.offer.celebrating { position: relative; }
.card.offer.celebrating::before, .card.offer.celebrating::after { position: absolute; inset: 0; border-radius: inherit; opacity: 0; pointer-events: none; content: ""; }
.card.offer.celebrating::before { z-index: -1; background: radial-gradient(ellipse at top, color-mix(in srgb, var(--green) 22%, transparent), transparent 75%); }
.card.offer.celebrating::after { box-shadow: inset 0 0 0 1px var(--green); }
.card.offer .check { position: absolute; top: 20px; right: 20px; width: 28px; height: 28px; border-radius: 14px; background-color: var(--green); opacity: 0; }
.card.offer .check::after { position: absolute; top: 6px; left: 10px; width: 7px; height: 12px; border: solid var(--black); border-width: 0 2.5px 2.5px 0; transform: rotate(45deg); content: ""; }

@media (prefers-reduced-motion: no-preference) {
    dialog.celebrate, dialog.celebrate::backdrop { transition: opacity .4s ease, transform .4s ease, display .4s allow-discrete, overlay .4s allow-discrete; }
    dialog.celebrate:not([open]), dialog.celebrate:not([open])::backdrop { opacity: 0; }
    dialog.celebrate:not([open]) { transform: scale(.5); }
    @starting-style {
        dialog.celebrate[open], dialog.celebrate[open]::backdrop { opacity: 0; }
        dialog.celebrate[open] { transform: scale(.5); }
    }

    .celebrate .member { --from: -6px; animation: celebrate-meet .55s ease both; }
    .celebrate .owner { --from: 6px; animation: celebrate-meet .55s ease both; }
    .celebrate .link { transform-box: fill-box; transform-origin: left; animation: celebrate-link .3s ease .45s both; }
    .celebrate .pulse { transform-box: fill-box; transform-origin: center; animation: celebrate-pulse .9s ease-out .8s; }
    .celebrate-copy > :not(.mark) { animation: celebrate-rise .4s ease calc(.85s + var(--i) * .05s) both; }

    /* .4s in: the dialog has just faded out */
    .card.offer.celebrating { animation: celebrate-lift 2.4s ease .4s both; }
    .card.offer.celebrating::before, .card.offer.celebrating::after { animation: celebrate-glow 2.4s ease .4s both; }
    .card.offer.celebrating .check { animation: celebrate-check 2.4s ease .4s both; }
    .card.offer.celebrating .acquired { animation: celebrate-pop .4s ease .9s both; }
}
@keyframes celebrate-meet { from { opacity: 0; transform: translateX(var(--from)); } }
@keyframes celebrate-link { from { transform: scaleX(0); } }
@keyframes celebrate-pulse { from { opacity: .8; } to { opacity: 0; transform: scale(3); } }
@keyframes celebrate-rise { from { opacity: 0; transform: translateY(32px); } }
@keyframes celebrate-lift { 15%, 85% { transform: translateY(-6px); } }
@keyframes celebrate-glow { 15%, 85% { opacity: 1; } }
@keyframes celebrate-check { 0% { transform: scale(.5); } 12%, 85% { opacity: 1; transform: none; } }
@keyframes celebrate-pop { from { opacity: 0; transform: scale(.5); } }

.empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: var(--padding-medium) var(--padding-small);
    text-align: center;
}
.empty svg { width: 64px; height: 64px; margin-bottom: 8px; }
.empty strong { font-size: 20px; }
.empty p { max-width: 360px; font-size: 16px; }

/* ---------------------------------------------------------------- board preview */

/* the landing hero shows a still of the offers board, built from the same
   parts as the live one in offers.html. */
.preview { display: flex; flex-direction: column; gap: var(--padding-extra-small); }
.preview .preview-head { display: flex; align-items: center; gap: 8px; }
.preview .preview-head strong { font-weight: 500; font-size: 18px; }

/* section 3 shows the whole board the same way: the live board's sidebar, head
   and cards in a window as wide as the section, frozen with inert. the page
   layout (fixed sidebar, full-height dashboard) is undone here, and the next
   offer lands at the front of the rail from pages/home.mjs. */
.board-shot { width: 100%; }
.board-window {
    display: flex; position: relative; isolation: isolate; overflow: hidden;
    border: 1px solid var(--color-background-elevation); border-radius: var(--border-radius-large);
    background-color: var(--color-background-primary); text-align: left;
}
.board-window .sidebar { position: static; z-index: auto; flex: none; overflow: visible; }
.board-window .dashboard { flex: 1; min-width: 0; min-height: 0; margin-left: 0; padding: 32px 0 32px 32px; }
.board-window .page-head { padding-right: 32px; }
/* cards as wide as the live board's, so two and a bit per view, the last one
   fading out: the rail goes on */
/* no snap: the live rail re-snaps to its old first card when one is prepended,
   which would scroll the landing card out of view */
.board-window .offers { overflow: hidden; scroll-snap-type: none; -webkit-mask-image: linear-gradient(to right, #000 80%, transparent); mask-image: linear-gradient(to right, #000 80%, transparent); }
.board-window .card.offer { flex-basis: calc((100% - var(--padding-small) * 2) / 2.4); }
@media only screen and (max-width: 1024px) { .board-window .card.offer { flex-basis: calc((100% - var(--padding-small)) / 1.6); } }
@media only screen and (max-width: 768px) {
    .board-window .dashboard { padding: 0 0 24px 16px; }
    .board-window .offers { flex-direction: row; }
    .board-window .card.offer { flex-basis: 88%; }
}

/* ---------------------------------------------------------------- keywords */

.keywords {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    min-height: 56px;
    padding: 8px;
    border: 1px solid transparent;
    border-radius: var(--border-radius-medium);
    background-color: var(--color-background-elevation);
}
.keywords:focus-within { border-color: var(--green); }
.keyword {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 32px;
    padding: 0 4px 0 12px;
    border-radius: 16px;
    background-color: var(--green);
    color: var(--black);
    font-weight: 500;
    font-size: 14px;
}
.keyword button { width: 24px; height: 24px; padding: 0; border-radius: 12px; background: none; color: var(--black); font-size: 16px; }
.keyword button:hover { background-color: rgba(0, 0, 0, .12); opacity: 1; }
.keywords input { flex: 1; min-width: 140px; height: 32px; padding: 0 8px; background: none; color: var(--color-primary); font-size: 16px; }

/* ---------------------------------------------------------------- accordion + plans */

.accordion { display: flex; flex-direction: column; }
.accordion .item { border-top: 1px solid var(--color-background-elevation); }
.accordion .item:first-child { border-top: none; }
.accordion summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: var(--padding-extra-small) 0;
    cursor: pointer;
    list-style: none;
    font-weight: 500;
    font-size: 20px;
}
.accordion summary::-webkit-details-marker { display: none; }
.accordion summary .chev { flex: none; width: 20px; height: 20px; transition: transform .15s ease; }
.accordion .item[open] summary .chev { transform: rotate(180deg); }
.accordion .body { display: flex; flex-direction: column; gap: var(--padding-extra-small); padding-bottom: var(--padding-small); }

.plans { display: grid; grid-template-columns: 1fr 1fr; gap: var(--padding-small); }
@media only screen and (max-width: 768px) { .plans { grid-template-columns: 1fr; } }
.plan .price, .checkout-summary .price { font-weight: 500; font-size: 40px; letter-spacing: -1px; }
.plan .price small, .checkout-summary .price small { font-size: 16px; letter-spacing: 0; }
/* the price stays in the dom, it is only obscured so this tier routes
   through a call instead of self serve checkout. */
.plan .price.obscured { filter: blur(14px); user-select: none; }
.plan ul, ul.checks { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0; list-style: none; }
.plan li, .checks li { display: flex; gap: 10px; font-size: 16px; color: var(--color-secondary); }
.plan li svg, .checks li svg { flex: none; width: 18px; height: 18px; margin-top: 3px; }
.plan .button { width: 100%; margin-top: auto; }

.narrow { width: 100%; max-width: 720px; margin: 0 auto; }
.narrow.slim { max-width: 520px; }
.card.plain { background-color: rgba(0, 0, 0, 0); padding: 0; }

.row-between > .stack { flex: 1; min-width: 260px; }

/* ---------------------------------------------------------------- hover states */

/* main.css fades every button to .8 opacity on hover. that washes the green out,
   does nothing readable for the grey ones, and reads as a dimmer rather than a
   response. replace it with a 1px lift plus one real colour step. */
:root.theme-light { --hover-elevation: rgba(0, 0, 0, .09); }
:root.theme-dark { --hover-elevation: rgba(255, 255, 255, .1); }

button, .button, .choice span, .theme-switch label, a.card {
    transition: transform .15s ease, background-color .15s ease, color .15s ease, opacity .15s ease;
}
button:not([disabled]):active, .button:not([disabled]):active { transform: translateY(0); }

/* touch taps leave :hover stuck on, so the lift is for pointers only */
@media (hover: hover) {
    button:not([disabled]):hover, .button:not([disabled]):hover,
    .choice span:hover, .theme-switch label:hover, a.card:hover { opacity: 1; transform: translateY(-1px); }

    /* filled surfaces step one shade darker */
    .button:not([disabled]):hover, .pin-submit:hover { background-color: color-mix(in srgb, var(--green) 88%, var(--black)); }
    .button.yellow:hover { background-color: color-mix(in srgb, var(--yellow) 88%, var(--black)); }
    .button.grey:hover { background-color: #999; }

    /* neutral surfaces step one shade stronger */
    .button.secondary:hover,
    dialog.modal .close:hover,
    header .header-content nav .icon-button:hover, .dashboard .icon-button:hover,
    header .header-content nav .dropdown:hover { background-color: var(--hover-elevation); }
    header .header-content nav .dropdown:hover { border-radius: var(--border-radius-small); }
    .rail-nav:not([disabled]):hover { background-color: color-mix(in srgb, var(--color-background-secondary) 92%, var(--color-primary)); }

    /* the onboarding pills and the theme toggle behave like buttons */
    .choice input:not(:checked) + span:hover,
    .theme-switch input:not(:checked) + label:hover { background-color: var(--hover-elevation); opacity: 1; }
    .choice input:checked + span:hover,
    .theme-switch input:checked + label:hover { background-color: color-mix(in srgb, var(--green) 88%, var(--black)); opacity: 1; }

    /* the booking calendar: open days, times and month arrows shade like the pills above */
    .booking .day:not([disabled]):not([aria-pressed="true"]):hover { background-color: color-mix(in srgb, var(--green) 30%, transparent); }
    .booking .slot:not([aria-pressed="true"]):hover, .booking .nav:not([disabled]):hover { background-color: var(--hover-elevation); }
    .booking .day[aria-pressed="true"]:hover, .booking .slot[aria-pressed="true"]:hover { background-color: color-mix(in srgb, var(--green) 88%, var(--black)); }

    /* no surface to shade, and nothing worth lifting: these shift colour instead */
    .theme-switch:hover, .keyword button:hover, .booking .day:hover,
    header .header-content nav .dropdown .dropdown-button:hover { transform: none; }
    .notif-panel .notif-head button:hover { transform: none; color: var(--color-primary); }
}

/* ---------------------------------------------------------------- logo mark */

/* the mark from the footer, at header scale. currentColor so it follows the
   theme exactly like the wordmark beside it. */
header .header-content .logo { display: inline-flex; align-items: center; gap: 8px; }
header .header-content .logo .logo-mark, .sidebar .logo-mark, .topbar .logo-mark, .booking .logo-mark { flex: none; width: 22px; height: 22px; }

/* ---------------------------------------------------------------- key recovery */

#recover .pin-row { gap: 8px; margin-top: 4px; }
#recover .input { max-width: 320px; }
#recover .button { flex: none; }

/* ---------------------------------------------------------------- checkout */

/* the story on the left, the form on the right and pinned while the story
   scrolls. one column below 1024px: price, then the form, then what happens
   next, so a phone reaches the pay button without scrolling past extras. */
.checkout-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 480px); grid-template-areas: "summary pay" "next pay"; gap: var(--padding-small) var(--padding-medium); align-items: start; }
@media only screen and (max-width: 1024px) { .checkout-grid { grid-template-columns: minmax(0, 1fr); grid-template-areas: "summary" "pay" "next"; gap: var(--padding-small); } }
/* the checkout and offer info (post-job.html) are one screen of work, so they
   start just under the header instead of at the content pages' full top margin. */
section.page.checkout, section.page.offer-info { padding-top: calc(var(--header-height) + var(--padding-extra-small)); }
section.page.offer-info { margin-bottom: var(--padding-extra-small); }
section.page.offer-info .section-content { gap: var(--padding-extra-small); }
.checkout-summary { grid-area: summary; gap: 24px; }
.checkout-summary h1 { margin: 0; }
.checkout-summary .price small { color: var(--color-secondary); }
.checkout-grid .next { grid-area: next; }
.checkout-grid .next ol { display: flex; flex-direction: column; gap: 6px; margin: 0; padding-left: 20px; color: var(--color-secondary); font-size: 16px; }

.order { gap: 12px; }
.order .line { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; font-size: 16px; color: var(--color-secondary); }
.order .line.discount { color: var(--green); }
.order .line.total { padding-top: var(--padding-extra-small); border-top: 1px solid var(--color-background-elevation); color: var(--color-primary); font-size: 18px; }
.order > small { color: var(--color-secondary); font-size: 14px; }
.order .link { padding: 0; background: none; color: inherit; font-size: 14px; text-decoration: underline; cursor: pointer; }
.order .promo summary { width: fit-content; color: var(--color-secondary); font-size: 14px; text-decoration: underline; cursor: pointer; list-style: none; }
.order .promo summary::-webkit-details-marker { display: none; }
.order .promo-row { display: flex; gap: 8px; margin-top: 8px; }
.order .promo-row .button { flex: none; height: 48px; margin: 0; }

.checkout-pay { grid-area: pay; position: sticky; top: calc(var(--header-height) + 16px); gap: var(--padding-extra-small); }
@media only screen and (max-width: 1024px) { .checkout-pay { position: static; } }
.checkout-pay .button { gap: 8px; width: 100%; max-width: none; margin: 8px 0 0; }
.checkout-pay .button svg { width: 18px; height: 18px; }
.checkout-pay .fine { color: var(--color-secondary); font-size: 13px; text-align: center; }
.checkout-pay .fine a { color: inherit; text-decoration: underline; }
.checkout-pay .stripe-note { display: flex; align-items: center; justify-content: center; gap: 6px; }
.checkout-pay .stripe-note svg { flex: none; width: 14px; height: 14px; }
.checkout .error { color: var(--red); font-size: 14px; }
.checkout .error:empty { display: none; }

/* wallet buttons take a moment to decide whether they show at all; the row
   stays collapsed until stripe reports at least one. */
.express { display: flex; flex-direction: column; gap: var(--padding-extra-small); }
.express:not(.ready) { height: 0; overflow: hidden; visibility: hidden; }
.divider { display: flex; align-items: center; gap: 12px; color: var(--color-secondary); font-size: 13px; }
.divider::before, .divider::after { content: ""; flex: 1; height: 1px; background-color: color-mix(in srgb, var(--color-primary) 12%, transparent); }

header .pill.secure { gap: 6px; height: 28px; padding: 0 12px; border-radius: 14px; color: var(--color-secondary); font-size: 13px; }
header .pill.secure svg { width: 14px; height: 14px; }
.checkout .paid svg { width: 56px; height: 56px; }

/* ---------------------------------------------------------------- post a job */

/* offer info is one screen of work on a pc: the fields card on the left in
   three columns, the pay structures on one row of their own; the card members
   will see, the description and submit on the right (pages/post-job.mjs). one
   column below 1180px, where the four pay chips would wrap beside the card:
   the card first, then the fields, then the description. the preview is the
   board's .card.offer without its rail sizing. */
.post-job { display: grid; grid-template-columns: minmax(0, 1fr) 340px; grid-template-rows: auto 1fr; grid-template-areas: "fields preview" "fields about"; gap: 28px var(--padding-small); align-items: start; width: 100%; }
.post-job-fields { grid-area: fields; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 28px var(--padding-extra-small); max-width: none; padding: 28px; }
.post-job-fields .full { grid-column: 1 / -1; }
/* the choices weigh what the inputs and the submit button do: as tall, the same corners */
.post-job .choices { gap: 12px; }
.post-job .choice span { height: 48px; border-radius: var(--border-radius-medium); }
/* the pay structures spread across the card, so that row ends where the others do */
.post-job-fields .full .choices { justify-content: space-between; }
/* hints run one or two lines; the controls of a row line up at its foot */
.post-job-fields .field > :last-child { margin-top: auto; }
.post-job-fields .field-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.post-job-preview { grid-area: preview; }
.post-job-preview .card.offer { flex: none; }
.post-job-preview .example { opacity: .45; }
.post-job-about { grid-area: about; }
.post-job-about .form-actions { margin-top: 0; }
/* the status line holds nothing while the form is open */
#ownerJobStatus:empty { display: none; }
@media only screen and (max-width: 1180px) {
    .post-job { grid-template-columns: minmax(0, 1fr); grid-template-areas: "preview" "fields" "about"; max-width: 800px; margin: 0 auto; }
    .post-job-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .post-job-fields .field-grid { grid-template-columns: minmax(0, 1fr); }
}
@media only screen and (max-width: 768px) {
    .post-job-fields, .post-job-fields .field-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ---------------------------------------------------------------- booking */

/* the fit call picker (static/js/calendar.mjs): what the call is, the month,
   then the picked day's times and next. three columns on a pc, where the times
   column takes its height from the month (contain: size) and scrolls its own
   list; the details form, then the booked note, take over the month and times
   columns. below 1024px .card caps at 512px and everything stacks. */
.card.booking { display: grid; grid-template-columns: minmax(0, 1fr) 308px 176px; gap: var(--padding-small); max-width: 1024px; margin: 0 auto; }
.booking .about { display: flex; flex-direction: column; gap: 12px; padding-right: var(--padding-small); border-right: 1px solid color-mix(in srgb, var(--color-primary) 12%, transparent); }
.booking .brand { display: inline-flex; align-items: center; gap: 8px; margin-bottom: 8px; font-weight: 500; font-size: 20px; letter-spacing: -1px; }
.booking .facts { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0; list-style: none; color: var(--color-secondary); font-size: 16px; }
.booking .facts li { display: flex; align-items: center; gap: 10px; }
.booking .facts svg { flex: none; width: 18px; height: 18px; }
.booking .facts .when { color: var(--color-primary); font-weight: 500; }
.booking .facts .when svg { color: var(--green); }
.booking .about p { margin-top: 8px; font-size: 16px; }
.booking > .empty, .booking .details, .booking .booked { grid-column: 2 / -1; }

.booking .month-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }
.booking .month-head .label { font-weight: 500; font-size: 18px; }
.booking .nav { width: 36px; height: 36px; padding: 0; border-radius: var(--border-radius-small); background-color: var(--color-background-elevation); color: var(--color-primary); }
.booking .nav svg { width: 18px; height: 18px; }
.booking .nav[disabled] { opacity: .3; cursor: default; }
.booking .weekdays, .booking .days { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); justify-items: center; }
.booking .weekdays { margin-bottom: 8px; color: var(--color-secondary); font-size: 13px; }
.booking .days { row-gap: 4px; }
/* open days carry a green wash, the picked one is solid green; today keeps a quiet ring */
.booking .day { width: 100%; max-width: 40px; height: auto; aspect-ratio: 1; padding: 0; border-radius: 50%; background-color: color-mix(in srgb, var(--green) 16%, transparent); color: var(--color-primary); font-weight: 500; font-size: 16px; font-variant-numeric: tabular-nums; }
.booking .day.today { box-shadow: inset 0 0 0 1px var(--color-secondary); }
.booking .day[disabled] { background: none; color: var(--color-secondary); font-weight: 400; opacity: .5; cursor: default; }
.booking .day[aria-pressed="true"], .booking .slot[aria-pressed="true"] { background-color: var(--green); color: var(--black); }
.booking button:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

.booking .times { display: flex; flex-direction: column; gap: 16px; min-height: 0; contain: size; }
.booking .times h3 { font-size: 16px; }
.booking .times p { font-size: 16px; }
/* the list's own 16px scrollbar (main.css) hangs in the card's padding, so the times line up with next */
.booking .slots { display: flex; flex-direction: column; gap: 8px; min-height: 0; margin-right: -16px; overflow-y: auto; scrollbar-gutter: stable; }
.booking .times .button { flex: none; width: 100%; }
.booking .slot { flex: none; width: 100%; height: 44px; padding: 0 16px; border-radius: 22px; background-color: var(--color-background-elevation); color: var(--color-primary); font-weight: 500; font-size: 16px; font-variant-numeric: tabular-nums; }

.booking .details { display: flex; flex-direction: column; gap: var(--padding-extra-small); }
.booking .details-head { display: flex; align-items: center; gap: 12px; }
.booking .details-head h3 { font-size: 20px; }
.booking .details textarea.input { height: auto; padding: 12px 16px; resize: vertical; }
.booking .details .button { width: 100%; margin-top: 8px; }
.booking .error { color: var(--red); }
.booking .error:empty { display: none; }
.booking .error a { color: var(--color-primary); font-weight: 500; text-decoration: underline; }
.booking .booked { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; text-align: center; }
.booking .booked svg { width: 56px; height: 56px; color: var(--green); }
.booking .booked h3 { font-size: 24px; }
.booking .booked h3:focus { outline: none; }
.booking .booked p { max-width: 400px; font-size: 16px; }

@media only screen and (max-width: 1024px) {
    .card.booking { grid-template-columns: minmax(0, 1fr); }
    .booking .about { padding: 0 0 var(--padding-small); border-right: none; border-bottom: 1px solid color-mix(in srgb, var(--color-primary) 12%, transparent); }
    .booking > .empty, .booking .details, .booking .booked { grid-column: auto; }
    .booking .times { contain: none; }
    .booking .slots { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); margin-right: 0; overflow: visible; }
    /* the pill grid runs past a phone's screen, so next rides along at its foot */
    .booking .times .button { position: sticky; bottom: var(--padding-extra-small); }
}

/* a new month slides in from the side it came from; a day's times rise in; each step fades in */
@media (prefers-reduced-motion: no-preference) {
    .booking .days, .booking .slots, .booking .details, .booking .booked { transition: opacity .3s ease, transform .3s ease; }
    @starting-style {
        .booking .days, .booking .slots, .booking .details, .booking .booked { opacity: 0; }
        .booking .days[data-slide="next"] { transform: translateX(8px); }
        .booking .days[data-slide="back"] { transform: translateX(-8px); }
        .booking .slots { transform: translateY(4px); }
    }
}
