/* ==========================================================================
   InOutBoard marketing site — shared stylesheet
   One file, linked by every page. Brand palette taken from the existing
   logo (#00AEEF) and theme (#1b232f navy, Untitled-UI style gray ramp).
   ========================================================================== */

/* --- Design tokens ------------------------------------------------------- */
:root {
    /* Brand */
    --brand: #00aeef;
    --brand-dark: #0090c7;
    --brand-darker: #00719c;
    --brand-tint: #e6f7fe;
    /* Neutrals */
    --navy: #1b232f;
    --navy-deep: #151a26;
    --navy-light: #2d384a;
    --gray-900: #101828;
    --gray-700: #344054;
    --gray-600: #475467;
    --gray-500: #667085;
    --gray-400: #98a2b3;
    --gray-300: #d0d5dd;
    --gray-200: #eaecf0;
    --gray-100: #f2f4f7;
    --gray-50: #f9fafb;
    --white: #ffffff;
    /* Text on light backgrounds. Dark sections (CTA band, footer) keep their
     own light colors so they stay legible. */
    --text: #000000;
    /* Accents */
    --gold: #fec84b;
    --green: #12b76a;
    /* Keyboard focus indicator. Deliberately not --brand -- the cyan is too
       light to ring anything on a pale background. See :focus-visible. */
    --focus-ring: var(--navy);
    --focus-ring-inner: var(--white);
    /* Typography */
    --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    /* Handwritten display face for headings; self-hosted, see Typefaces below */
    --font-display: "Caveat", "Segoe Print", "Comic Sans MS", cursive;
    /* Spacing / layout */
    --container: 1200px;
    --container-narrow: 900px;
    /* Width of the framed video column. Anything that has to line up under a
       video reads it from here rather than repeating the number -- see
       .video-wrap and .transcript. Narrower per-context overrides (the help
       topic pages put a video at 640px) set max-width directly instead. */
    --video-max: 880px;
    /* Gap between a video's runtime label and the player underneath it. One
       token so every placement keeps the same spacing -- see
       .video-split__duration. */
    --video-label-gap: 12px;
    --radius-sm: 8px;
    --radius: 12px;
    --radius-lg: 16px;
    --radius-xl: 24px;
    /* Shadows */
    --shadow-sm: 0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .10);
    --shadow-md: 0 4px 8px -2px rgba(16, 24, 40, .10), 0 2px 4px -2px rgba(16, 24, 40, .06);
    --shadow-lg: 0 12px 16px -4px rgba(16, 24, 40, .08), 0 4px 6px -2px rgba(16, 24, 40, .03);
    --shadow-xl: 0 20px 24px -4px rgba(16, 24, 40, .08), 0 8px 8px -4px rgba(16, 24, 40, .03);
    /* The screenshot frame, one look for every product screenshot on the site:
       a white 10px border (18px corners outside, 8px inside) and this neutral
       blue-grey two-layer shadow. It is the look of the dashboard feature page's
       .video-wrap, which is the one to match. */
    --shadow-shot: 0 0 24px rgba(16, 24, 40, .14), 0 16px 32px -8px rgba(16, 24, 40, .18);
    --frame-radius: calc(var(--radius-sm) + 10px);
}

/* --- Typefaces ------------------------------------------------------------
   Inter and Caveat, self-hosted from /fonts/ since Oct 2026. They came from
   Google Fonts until then, which meant two extra origins on every page view,
   each visitor's IP address sent to Google to draw text, and the site's look
   tied to whatever Google served behind that URL that day.

   These are byte-for-byte the files App/fonts/ has used since Sep 2026 (see
   the comment in App/css/brand.css): the @fontsource-variable 5.2.5 builds of
   the upstream Google Fonts files, variable Latin subsets, 48KB and 74KB,
   SIL Open Font License 1.1 with the licences beside them. Keep the two
   copies identical, so the marketing site and the sign-up page render the
   same type.

   Latin only, like the App. The only characters any page uses outside it are
   the arrows (U+2190, U+2192), which no subset Google served for Inter
   covered either, so they were already drawn by the fallback stack. Measured
   Oct 2026 by rendering every page with both sources: text boxes identical.

   Never edit a file in place: /fonts/ is served with a one-year immutable
   cache (web.config), so a new build needs a new file name. .woff2 needs its
   MIME map in web.config too -- App Service 404s the extension without one,
   which App/Web.config records as measured, not assumed. */
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-display: swap;
    font-weight: 100 900;
    src: url('../fonts/inter-latin-wght-normal.woff2') format('woff2-variations');
    unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

@font-face {
    font-family: 'Caveat';
    font-style: normal;
    font-display: swap;
    font-weight: 400 700;
    src: url('../fonts/caveat-latin-wght-normal.woff2') format('woff2-variations');
    unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

/* --- Reset --------------------------------------------------------------- */
*, *::before, *::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    /* Offset for the sticky header when jumping to #anchors */
    scroll-padding-top: 90px;
}

body {
    margin: 0;
    font-family: var(--font-sans);
    font-size: 1.25rem;
    line-height: 1.6;
    color: var(--text);
    background: var(--white);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
    margin: 0 0 .5em;
    color: var(--text);
    line-height: 1.2;
    letter-spacing: -.02em;
    font-weight: 700;
}

h1 {
    font-size: clamp(2.25rem, 5vw, 3.5rem);
}

h2 {
    font-size: clamp(1.75rem, 3.5vw, 2.5rem);
}

h3 {
    font-size: 1.5rem;
}

p {
    margin: 0 0 1rem;
}

    p:last-child {
        margin-bottom: 0;
    }

a {
    color: var(--brand-darker);
    text-decoration: none;
}

    a:hover {
        text-decoration: underline;
    }

img, svg, iframe {
    max-width: 100%;
}

img {
    height: auto;
    border: 0;
}

ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Visible keyboard focus everywhere — do not remove.

   Two-tone ring: a dark band with a white band inside it. One of the two
   always clears 3:1 against whatever sits behind, which a single band cannot
   do across this palette (WCAG 2.2 SC 1.4.11). The dark band carries the
   white and --gray-50 sections and the filled cyan buttons; the white band
   carries the navy footer and navy sections, where the dark band disappears
   into its background. The box-shadow spread matches outline-offset exactly,
   so the gap is filled and the two bands read as one ring.

   This used to be a single --brand ring, which failed on the light
   backgrounds it sat on most: #00aeef is 2.53:1 on white and 2.42:1 on the
   --gray-50 tint. Only the indicator moved off brand -- links, buttons and
   decoration still use --brand. */
:focus-visible {
    outline: 3px solid var(--focus-ring);
    outline-offset: 2px;
    box-shadow: 0 0 0 2px var(--focus-ring-inner);
    border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

    *, *::before, *::after {
        animation-duration: .01ms !important;
        transition-duration: .01ms !important;
    }
}

/* --- Utilities ----------------------------------------------------------- */
.container {
    width: 100%;
    max-width: var(--container);
    margin: 0 auto;
    padding: 0 24px;
}

.section {
    padding: clamp(56px, 8vw, 96px) 0;
}

/* Interior pages open with a hero built from a plain .section; pull it up
   toward the nav with the same top padding as the home page .hero, instead
   of leaving a full between-sections gap under the header. */
main > .section:first-child {
    padding-top: clamp(32px, 4vw, 56px);
}

.section--tint {
    background: var(--gray-50);
}

.section--navy {
    background: var(--navy);
    color: var(--gray-300);
}

    .section--navy h2, .section--navy h3 {
        color: var(--white);
    }

.section-head {
    max-width: 1040px;
    margin: 0 auto clamp(40px, 5vw, 64px);
    text-align: center;
}
    /* Section titles share the hero's handwritten display treatment. Script
   faces read smaller than sans at the same size, so these run larger than
   the base h2 scale. Card/panel h3s stay in the sans for readability. */
    .section-head h1,
    .section-head h2 {
        font-family: var(--font-display);
        font-size: clamp(1.75rem, 6.1vw, 4rem);
        line-height: 1.15;
        letter-spacing: 0;
        text-wrap: balance;
    }

    /* Page titles (feature/industry heroes and the like) keep the same scale
       on desktop but bottom out at the home hero's 2.75rem floor instead of
       1.75rem, so phones aren't left with an undersized headline. */
    .section-head h1 {
        font-size: clamp(2.75rem, 6.1vw, 4rem);
    }

    /* Opt-out for pages (e.g. legal) where the script face is out of place. */
    .section-head--plain h1,
    .section-head--plain h2 {
        font-family: var(--font-sans);
        font-size: clamp(2.25rem, 5vw, 3.5rem);
        line-height: 1.2;
        letter-spacing: -.02em;
    }

    .section-head p {
        font-size: calc(1.275rem + 0.3vw);
        color: var(--text);
    }

    /* One-off for the home page intro above the feature tiles. Balanced so
       the last line is not left holding a single word, and capped near 60ch
       so the measure stays comfortable on a wide screen -- min() keeps it
       inside the container on a phone rather than overflowing. font-size
       inherits, preserving the size this text had before it was wrapped in
       a <p>; margin is pinned so the wrapper adds no vertical space. */
    .section-head .section-head__intro {
        max-width: min(60ch, 100%);
        margin: 0 auto;
        font-size: inherit;
        text-wrap: balance;
    }

    /* Quiet second row under a section-head title, e.g. a legal page's
       effective date. */
    .section-head .section-head__sub {
        margin-top: 8px;
        font-size: 1rem;
        color: var(--gray-500);
    }

    /* Eyebrow above a page title — the plain, descriptive name for what the
       page is about, sitting over a headline that is deliberately not plain.

       The feature pages are what this exists for. Their h1s are slogans
       ("Smarter insights, better decisions"), which is the house voice and is
       staying; the term a visitor actually searched for had nowhere to go on
       the page as a result. The industry pages never had the problem because
       their titles name the industry outright ("The status board for
       Healthcare & Social Services").

       Sans, not the display face: it is a label, and setting it in Caveat
       alongside a Caveat headline would read as two headlines.

       On the feature pages, /emergency-roll-call/ and /hybrid-work/ it sits
       INSIDE the <h1> (since Oct 2026), so the searched-for term is part of
       the heading and not a stray span above it: the h1 is the strongest
       on-page statement of what a page is about, for search engines and for
       the AI answer engines that quote it. Every property that would
       otherwise inherit from the h1 -- face, size, weight, line-height,
       letter-spacing, colour -- is set explicitly below, so it looks the same
       in either position. The .sr-only ": " after the label keeps the
       heading's text from running the two parts together, for screen readers
       and for anything that reads the heading as plain text. */
    .section-head .section-head__eyebrow {
        display: block;
        margin-bottom: 10px;
        font-family: var(--font-sans);
        font-size: .8125rem;
        font-weight: 600;
        line-height: 1.3;
        letter-spacing: .08em;
        text-transform: uppercase;
        color: var(--brand-darker);
        text-wrap: balance;
    }

    /* Pricing link under the /features/ hub intro, on its own centred line
       right below the paragraph -- normal <p> spacing between the two is
       already modest, so no extra margin is added here. Matches the
       ".cta__price a" / ".usecase__more" action-link treatment: brand-darker
       blue and the no-underline default already come from the global `a`
       rule, the hover underline from a:hover, and keyboard focus from
       :focus-visible, so only the weight is declared. nowrap keeps the
       trailing arrow from stranding onto its own line. */
    .section-head .section-head__pricing-link a {
        font-weight: 600;
        white-space: nowrap;
    }

.section--navy .section-head p {
    color: var(--gray-400);
}

.section-footer {
    max-width: 1040px;
    margin: clamp(40px, 5vw, 64px) auto 0;
    text-align: center;
}

/* Feature benefits split: checkmark list on the left, product shot on the
   right. Stacks on narrow screens with the image last. */
.feature-split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(28px, 4vw, 60px);
    align-items: center;
    text-align: left;
}

    /* Half the width, so the list runs as a single column here. */
    .feature-split .check-list {
        grid-template-columns: 1fr;
        margin-top: 0;
    }

/* Was a transparent PNG mockup with its own baked-in shadow; now a flat
   screenshot (status-board-cards), so the shadow comes from CSS. Only
   /what-is-inoutboard/ uses this class -- do not put a transparent PNG back
   in it or the shadow will outline the rectangle. */
.feature-split__media {
    width: 100%;
    max-width: 520px;
    justify-self: end;
}

    .feature-split__media img {
        display: block;
        width: 100%;
        box-sizing: border-box;
        border: 10px solid var(--white);
        border-radius: var(--frame-radius);
        background: var(--white);
        box-shadow: var(--shadow-shot);
    }

@media (max-width: 860px) {
    .feature-split {
        grid-template-columns: 1fr;
    }

    .feature-split__media {
        justify-self: center;
    }
}

/* --- /features/ hub closing section --------------------------------------
   "How the features work together": two columns on desktop (explanatory
   text left, a real screenshot right), stacking with the text first on
   narrow screens because that is already the source order -- no reordering
   needed. Scoped to this one section rather than reused from .feature-split
   (built for a checklist beside a transparent PNG mockup with no card
   treatment) or .showcase (puts its image first on mobile, which we don't
   want here). The screenshot instead gets the same bordered, rounded,
   shadowed card treatment as .showcase__media, since this is a plain
   rectangular product screenshot rather than a pre-shadowed cutout. */
.features-summary__grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(28px, 4vw, 60px);
    align-items: center;
    text-align: left;
}

.features-summary__shot {
    border: 10px solid var(--white);
    border-radius: var(--frame-radius);
    box-shadow: var(--shadow-shot);
    overflow: hidden;
    background: var(--white);
}

    .features-summary__shot img {
        display: block;
        width: 100%;
        height: auto;
    }

@media (max-width: 860px) {
    .features-summary__grid {
        grid-template-columns: 1fr;
    }
}

/* Checkmark list — two columns on desktop, one on narrow screens. Items are
   left-aligned while the block itself stays centred in the section. */
.check-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
    gap: 14px 40px;
    margin-top: 28px;
    text-align: left;
}

    .check-list li {
        position: relative;
        padding-left: 32px;
        font-size: 1.125rem;
        line-height: 1.5;
    }

    .check-list svg {
        position: absolute;
        left: 0;
        top: 4px;
        color: var(--green);
    }

    .check-list em {
        font-style: normal;
        color: var(--brand-darker);
    }

    /* A screenshot directly after a check-list sits flush against it
       otherwise: .check-list carries no bottom margin and .video-wrap no top
       one, so the two blocks touch. Used by /features/reports/,
       /features/set-up/, /features/dashboard/ and /features/calendar/. Same
       step .section-footer uses to separate itself from the block above,
       rather than a new value. */
    .check-list + .video-wrap,
    .check-list + .shot-stack {
        margin-top: clamp(40px, 5vw, 64px);
    }

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 200;
    padding: 12px 20px;
    background: var(--navy);
    color: var(--white);
    border-radius: 0 0 var(--radius-sm) 0;
}

    .skip-link:focus {
        left: 0;
    }

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* --- Buttons ------------------------------------------------------------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 13px 24px;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    font-family: inherit;
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.25;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease, transform .15s ease, box-shadow .15s ease;
}

    .btn:hover {
        text-decoration: none;
    }

    .btn:active {
        transform: translateY(1px);
    }

.btn--primary {
    background: var(--brand);
    border-color: var(--brand);
    color: var(--white);
    box-shadow: var(--shadow-sm);
}

    .btn--primary:hover {
        background: var(--brand-dark);
        border-color: var(--brand-dark);
    }

.btn--secondary {
    background: var(--white);
    border-color: var(--gray-300);
    color: var(--text);
    box-shadow: var(--shadow-sm);
}

    .btn--secondary:hover {
        background: var(--gray-50);
        border-color: var(--gray-400);
    }

    /* The focus ring paints its white band as a box-shadow, which would
       otherwise replace the resting shadow these two carry. Re-state that
       shadow behind the band so a focused button keeps its lift. */
    .btn--primary:focus-visible,
    .btn--secondary:focus-visible {
        box-shadow: 0 0 0 2px var(--focus-ring-inner), var(--shadow-sm);
    }

.btn--ghost-light {
    background: rgba(255, 255, 255, .10);
    border-color: rgba(255, 255, 255, .30);
    color: var(--white);
}

    .btn--ghost-light:hover {
        background: rgba(255, 255, 255, .18);
    }

.btn--lg {
    padding: 16px 32px;
    font-size: 1.0625rem;
}

.btn--block {
    width: 100%;
}

/* Compact button for a table row (the trial links in the /pricing/ license
   table). Still clears the 24px minimum target size. */
.btn--sm {
    padding: 7px 14px;
    font-size: .875rem;
    white-space: nowrap;
}

/* --- Header / nav -------------------------------------------------------- */
.site-header {
    position: sticky;
    top: 0;
    z-index: 100;
    background: rgba(255, 255, 255, .92);
    backdrop-filter: blur(10px);
}

.site-header__inner {
    display: flex;
    align-items: center;
    gap: 32px;
    min-height: 72px;
}

.site-logo {
    flex: none;
    display: flex;
    align-items: center;
}

    .site-logo img {
        display: block;
        width: 190px;
        height: auto;
    }

.nav {
    flex: 1;
}

.nav__list {
    display: flex;
    align-items: center;
    /* Centres the links in the flexible space between the logo and the
       log-in/try buttons. Overridden in the collapsed mobile menu, where
       the list stacks vertically. */
    justify-content: center;
    gap: 4px;
}

.nav__link {
    display: block;
    padding: 8px 14px;
    border-radius: var(--radius-sm);
    font-size: .9375rem;
    font-weight: 500;
    color: var(--text);
}

    .nav__link:hover {
        background: var(--gray-100);
        color: var(--text);
        text-decoration: none;
    }

    .nav__link[aria-current="page"] {
        color: var(--brand-darker);
        font-weight: 600;
    }

/* --- Nav dropdowns -------------------------------------------------------
   Click to open (handled in site.js). The panel is absolutely positioned on
   desktop and flows inline inside the collapsed mobile menu. */
.nav__item--menu {
    position: relative;
}

/* The Industries entry exists twice: the dropdown (--desktop) and a plain
   link to /industry/ (--mobile). Swapped at the 1000px nav breakpoint below.
   display:none rather than visibility/clip so the hidden one contributes no
   focusable links to the collapsed menu. */
.nav__item--mobile {
    display: none;
}

.nav__button {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: 0;
    font-family: inherit;
    cursor: pointer;
}

    .nav__button .nav__caret {
        transition: transform .15s ease;
    }

    .nav__button[aria-expanded="true"] {
        background: var(--gray-100);
        color: var(--gray-900);
    }

        .nav__button[aria-expanded="true"] .nav__caret {
            transform: rotate(180deg);
        }

.nav__menu {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    z-index: 120;
    min-width: 240px;
    padding: 10px;
    background: var(--white);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
}

    .nav__menu[hidden] {
        display: none;
    }

/* Thirteen industries need two columns so the panel is not absurdly tall.
   Sized to the longest short label ("Engineering & Construction", 166px) plus
   padding, with a little slack — if the labels grow, re-measure this. */
.nav__menu--wide {
    min-width: 440px;
}

    .nav__menu--wide .nav__menu-list {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 0 8px;
    }

/* Small, loose and in the dark slate rather than --text (pure black): a long
   list of black links at a tight line-height is high-contrast and cramped
   enough to be tiring to scan. Matching the compact treatment Odoo uses in
   its nav panels — the readability comes from the colour and the row spacing,
   not from the type size. */
.nav__menu-list a,
.nav__menu-all {
    display: block;
    padding: 8px 14px;
    border-radius: var(--radius-sm);
    font-size: .8rem;
    font-weight: 400;
    line-height: 1.5;
    /* Deliberate one-off. Dark enough to read crisply at this size, but kept
       off pure black (--text) — a long column of #000 links is what made this
       menu tiring in the first place. */
    color: #1f2937;
}

    .nav__menu-list a:hover,
    .nav__menu-all:hover {
        background: var(--gray-100);
        text-decoration: none;
    }

.nav__menu-all {
    margin-top: 6px;
    padding-top: 12px;
    border-top: 1px solid var(--gray-200);
    font-weight: 400;
    color: var(--brand-darker);
    border-radius: 0;
}

@media (max-width: 1000px) {
    /* Industries collapses to a single link to the /industry/ directory. The
       dropdown is display:none, so its 18 links leave the focus order too. */
    .nav__item--desktop {
        display: none;
    }

    .nav__item--mobile {
        display: block;
    }

    /* Inside the collapsed menu the panel sits in the flow, indented. */
    .nav__menu {
        position: static;
        min-width: 0;
        margin: 4px 0 8px 14px;
        box-shadow: none;
    }

    .nav__menu--wide {
        min-width: 0;
    }

        .nav__menu--wide .nav__menu-list {
            grid-template-columns: 1fr;
        }

    .nav__button {
        width: 100%;
        justify-content: space-between;
    }

    /* Desktop rows are tuned for scanning with a mouse; on touch they have to
       clear the 44px minimum tap target, so pad them back out here. */
    .nav__menu-list a,
    .nav__menu-all {
        padding: 13px 14px;
    }
}

.header-actions {
    flex: none;
    display: flex;
    align-items: center;
    gap: 12px;
}

    .header-actions .btn {
        padding: 10px 20px;
        font-size: .9375rem;
    }

.nav-toggle {
    display: none;
    flex: none;
    width: 44px;
    height: 44px;
    margin-left: auto;
    padding: 0;
    background: none;
    border: 1px solid var(--gray-300);
    border-radius: var(--radius-sm);
    color: var(--text);
    cursor: pointer;
}

    .nav-toggle svg {
        display: block;
        margin: auto;
    }

    .nav-toggle .icon-close {
        display: none;
    }

    .nav-toggle[aria-expanded="true"] .icon-open {
        display: none;
    }

    .nav-toggle[aria-expanded="true"] .icon-close {
        display: block;
    }

@media (max-width: 1000px) {
    .nav-toggle {
        display: block;
    }

    .nav, .header-actions {
        display: none;
        width: 100%;
    }

    .site-header__inner {
        flex-wrap: wrap;
        gap: 0;
        padding-bottom: 0;
    }

        .site-header__inner.is-open {
            padding-bottom: 20px;
        }

            .site-header__inner.is-open .nav,
            .site-header__inner.is-open .header-actions {
                display: block;
            }

    .nav__list {
        flex-direction: column;
        align-items: stretch;
        gap: 2px;
        padding: 12px 0;
    }

    .nav__link {
        padding: 12px 14px;
        font-size: 1rem;
    }

    .header-actions {
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
    }

        .header-actions .btn {
            width: 100%;
            padding: 13px 20px;
        }
}


/* --- Breadcrumb ----------------------------------------------------------
   Rendered by Common/Site.master at the top of <main>, on pages two levels
   down only (/features/*, /industry/*, /help/*). The same trail is emitted as
   BreadcrumbList JSON-LD in <head>; this is the visible half of that pair,
   and Google's structured data guidelines require it to exist.

   It sits above the first section's own top padding rather than inside it,
   so every page underneath keeps the spacing it already had.
   -------------------------------------------------------------------------- */
.breadcrumb {
    padding-top: 20px;
}

.breadcrumb ol {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 8px;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: 14px;
    color: var(--gray-500);
}

    /* The separator is decorative, so it is generated rather than marked up:
       a screen reader reads the list as a list and does not need to hear a
       slash between every item. */
    .breadcrumb li + li::before {
        content: "/";
        margin-right: 8px;
        color: var(--gray-300);
    }

    .breadcrumb a {
        color: var(--gray-600);
        text-decoration: none;
    }

        .breadcrumb a:hover {
            color: var(--brand-darker);
            text-decoration: underline;
        }

    .breadcrumb [aria-current="page"] {
        color: var(--gray-500);
    }

@media (max-width: 600px) {
    .breadcrumb {
        padding-top: 16px;
    }

    .breadcrumb ol {
        font-size: 13px;
    }
}


/* --- Hero ---------------------------------------------------------------- */
.hero {
    position: relative;
    padding: clamp(20px, 2.5vw, 36px) 0 clamp(40px, 5vw, 72px);
    background: var(--white);
    overflow: hidden;
}

/* Home hero: stacked and centred on narrow screens (headline, sub-line, buttons,
   then the laptop); from 861px it becomes copy-left, laptop-right on roughly
   equal columns, vertically centred against each other. */
.hero__split {
    text-align: center;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(24px, 5vw, 36px);
}

@media (min-width: 861px) {
    .hero__split {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        gap: clamp(28px, 4vw, 56px);
        align-items: center;
        text-align: left;
    }

    .hero__sub {
        margin-inline: 0;
    }

    .hero__actions {
        justify-content: flex-start;
        align-items: flex-start;
    }

    .hero__cta {
        align-items: flex-start;
    }
}

/* A laptop drawn in CSS around a screenshot: dark lid with a camera dot, the
   screen at 16:10, and a base with a thumb notch. Padding is a percentage of the
   width, so the whole thing scales as one piece. The drop-shadow follows the
   outline (box-shadow would not). */
.laptop {
    position: relative;
    width: 100%;
    max-width: 640px;
    margin-inline: auto;
    filter: drop-shadow(0 0 12px rgba(16, 24, 40, .14)) drop-shadow(0 14px 18px rgba(16, 24, 40, .16));
}

.laptop__lid {
    position: relative;
    padding: 2.4% 2.4% 3%;
    border-radius: 16px 16px 6px 6px;
    background: linear-gradient(#2b3340, #1b212b);
}

    .laptop__lid::before {
        content: "";
        position: absolute;
        top: 1.1%;
        left: 50%;
        width: 5px;
        height: 5px;
        margin-left: -2.5px;
        border-radius: 50%;
        background: #3b4452;
    }

.laptop__screen {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 10;
    border-radius: 4px;
    background: var(--white);
}

.laptop__base {
    position: relative;
    height: clamp(8px, 1.8vw, 14px);
    margin-inline: -5%;
    border-radius: 0 0 14px 14px / 0 0 10px 10px;
    background: linear-gradient(#e5e7eb, #b9bec7);
}

    .laptop__base::after {
        content: "";
        position: absolute;
        left: 50%;
        top: 0;
        width: 16%;
        height: 45%;
        transform: translateX(-50%);
        border-radius: 0 0 8px 8px;
        background: #c9cdd4;
    }

.hero h1 {
    /* Sized for the half-width column it now sits in and left to wrap on its
       own -- no breakout width or one-line tuning. text-wrap: balance evens
       the lines out, and the highlight span carries box-decoration-break:
       clone, so the marker band repeats correctly across a wrap. */
    margin-bottom: .1em;
    /* Handwritten display treatment. Script faces read smaller than sans
     at the same size, so scale up and drop the negative tracking used by
     the sans headings. */
    font-family: var(--font-display);
    font-size: clamp(2.5rem, 5.6vw, 4.75rem);
    line-height: 1.15;
    letter-spacing: 0;
    text-wrap: balance;
}

/* --- Hand-drawn marker accents ------------------------------------------
   Inline-SVG backgrounds so the strokes have rough, organic edges. The
   padding + negative margin let the ink spill past the word without
   changing the text layout. Reusable on any inline span. */
.marker-highlight {
    padding: .02em .22em .06em;
    margin-inline: -.22em;
    /* Three stacked marker passes: the top swipe starts indented and runs
     long to the right, the middle spans full width, and the bottom swipe
     is shorter with its tail out to the lower left. Each pass is
     semi-transparent so the overlaps darken like real marker ink. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 100' preserveAspectRatio='none'%3E%3Cg opacity='.75' fill='%23fbb945' transform='rotate(-3 150 50)'%3E%3Cpath d='M52 20 C130 17 230 16 280 19 C294 20 294 43 280 44 C210 47 130 48 52 46 C38 45 38 21 52 20 Z'/%3E%3Cpath d='M20 34 C110 31 240 30 284 33 C298 34 298 57 284 58 C230 61 110 62 20 60 C6 59 6 35 20 34 Z'/%3E%3Cpath d='M30 54 C100 51 210 50 268 53 C282 54 282 77 268 78 C200 81 100 82 30 80 C16 79 16 55 30 54 Z'/%3E%3C/g%3E%3C/svg%3E");
    /* Band height lives here so every highlight, in any colour, matches. */
    background-size: 100% 74%;
    background-position: 0 46%;
    background-repeat: no-repeat;
    box-decoration-break: clone;
    -webkit-box-decoration-break: clone;
}

/* Gold variant of the marker highlight. Gold is also the base ink, so on its
   own this changes nothing today -- it exists because one heading names the
   colour explicitly and .marker-underline--gold already does the same, and a
   class the markup references should not be missing from the stylesheet.
   Declaring the pass here rather than leaning on the base also means that
   recolouring .marker-highlight later leaves the explicitly-gold callers
   gold, which is the whole point of a named modifier. */
.marker-highlight--gold {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 100' preserveAspectRatio='none'%3E%3Cg opacity='.75' fill='%23fbb945' transform='rotate(-3 150 50)'%3E%3Cpath d='M52 20 C130 17 230 16 280 19 C294 20 294 43 280 44 C210 47 130 48 52 46 C38 45 38 21 52 20 Z'/%3E%3Cpath d='M20 34 C110 31 240 30 284 33 C298 34 298 57 284 58 C230 61 110 62 20 60 C6 59 6 35 20 34 Z'/%3E%3Cpath d='M30 54 C100 51 210 50 268 53 C282 54 282 77 268 78 C200 81 100 82 30 80 C16 79 16 55 30 54 Z'/%3E%3C/g%3E%3C/svg%3E");
}

/* Coral variant of the marker highlight — same three passes, warmer ink. */
.marker-highlight--coral {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 100' preserveAspectRatio='none'%3E%3Cg opacity='.75' fill='%23ff6b6b' transform='rotate(-3 150 50)'%3E%3Cpath d='M52 20 C130 17 230 16 280 19 C294 20 294 43 280 44 C210 47 130 48 52 46 C38 45 38 21 52 20 Z'/%3E%3Cpath d='M20 34 C110 31 240 30 284 33 C298 34 298 57 284 58 C230 61 110 62 20 60 C6 59 6 35 20 34 Z'/%3E%3Cpath d='M30 54 C100 51 210 50 268 53 C282 54 282 77 268 78 C200 81 100 82 30 80 C16 79 16 55 30 54 Z'/%3E%3C/g%3E%3C/svg%3E");
}

/* Brush underline, e.g. <span class="marker-underline">affordable!</span>.
   The stroke rides just under the baseline and spills past both ends. */
.marker-underline {
    padding: 0 .06em .16em;
    margin-inline: -.06em;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 34' preserveAspectRatio='none'%3E%3Cpath d='M22 16 C80 8 180 4 276 9 C282 10 283 20 279 23 C190 16 95 21 26 30 C19 31 17 19 22 16 Z' fill='%2300aeef'/%3E%3C/svg%3E");
    background-size: 100% .42em;
    background-position: 50% 100%;
    background-repeat: no-repeat;
    box-decoration-break: clone;
    -webkit-box-decoration-break: clone;
}

/* Gold variant of the brush underline, matching the marker highlight. */
.marker-underline--gold {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 34' preserveAspectRatio='none'%3E%3Cpath d='M22 16 C80 8 180 4 276 9 C282 10 283 20 279 23 C190 16 95 21 26 30 C19 31 17 19 22 16 Z' fill='%23fbb945'/%3E%3C/svg%3E");
}

/* Second hero row. This carries the product description rather than a short
   slogan, so it reads as a lede in the sans face: the handwritten display
   face ran to three lines of 64px script on desktop at this length, and a
   script face is the wrong tool for a sentence doing informational work.
   The h1 above keeps the handwritten treatment and its marker highlight, so
   the hero keeps its character. Width cap holds lines near 60 characters. */
.hero__sub {
    max-width: 34em;
    margin-inline: auto;
    margin-bottom: clamp(24px, 3.4vw, 36px);
    font-size: clamp(1.0625rem, 1.55vw, 1.375rem);
    line-height: 1.45;
    color: var(--text);
    text-wrap: balance;
}

.hero__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    /* Top-aligned so "Talk to an expert" lines up with the primary button
       rather than centring against the taller button-plus-note column. */
    align-items: flex-start;
    gap: 12px;
    margin-bottom: 20px;
}

/* Primary call to action stacked with its reassurance line. */
.hero__cta {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
}

.hero__cta-note {
    font-size: .875rem;
    color: var(--gray-600);
}

/* Below this width the two buttons cannot sit side by side, and the longer
   primary label would wrap inside a shrink-to-fit button. Stack them
   full-width in a capped column instead, and trim the large-button side
   padding so the label still fits on one line at 320px. */
@media (max-width: 600px) {
    .hero__actions {
        flex-direction: column;
        align-items: stretch;
        width: 100%;
        max-width: 340px;
        margin-inline: auto;
    }

    .hero__cta {
        width: 100%;
        /* Stretch, so the button fills the column rather than shrinking to
           its label and sitting narrower than the secondary button. */
        align-items: stretch;
    }

    .hero__actions > .btn {
        width: 100%;
    }
}

@media (max-width: 380px) {
    .hero__actions .btn--lg {
        padding-inline: 14px;
        font-size: 1rem;
    }
}

.hero__reassure {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px 20px;
    font-size: .875rem;
    color: var(--text);
}

    .hero__reassure li {
        display: flex;
        align-items: center;
        gap: 6px;
    }

    .hero__reassure svg {
        flex: none;
        color: var(--green);
    }

.hero__media {
    position: relative;
    width: 100%;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-xl);
    background: var(--white);
    overflow: hidden;
}

    .hero__media img {
        display: block;
        width: 100%;
    }

/* --- Social proof strip -------------------------------------------------- */
.proof {
    padding: 28px 0;
    border-block: 1px solid var(--gray-200);
    background: var(--white);
}

.proof__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 16px 48px;
    text-align: center;
}

.proof__stat {
    display: flex;
    align-items: baseline;
    gap: 8px;
    /* These are <p>s: without this, the global paragraph bottom margin hits
       every stat except the last (p:last-child zeroes it), and the mismatch
       shifts the last stat visibly lower in the centered flex row. */
    margin: 0;
    font-size: 1.25rem;
    color: var(--text);
}

    .proof__stat b {
        font-size: 1.375rem;
        font-weight: 700;
        color: var(--text);
        letter-spacing: -.02em;
    }

.stars {
    display: inline-flex;
    gap: 2px;
    color: var(--gold);
    vertical-align: middle;
}

/* --- Card grids ---------------------------------------------------------- */
.grid {
    display: grid;
    gap: 24px;
}
/* Two fixed columns, not auto-fit: every .grid--2 on the site holds exactly
   four cards, and a full-width container fits three auto-fit tracks, which
   left the fourth card orphaned on a row of its own. Stacks under 720px,
   where two columns would be narrower than a card wants to be. */
.grid--2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (max-width: 720px) {
    .grid--2 {
        grid-template-columns: 1fr;
    }
}

/* min() keeps the track from ever exceeding the available width, so these
   never force horizontal scroll on narrow phones (e.g. 320px iPhone SE). */
.grid--3 {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
}

.grid--4 {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
}

.card {
    padding: 28px;
    background: var(--white);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    transition: box-shadow .2s ease, transform .2s ease, border-color .2s ease;
}

    .card h3 {
        margin-bottom: 8px;
    }

    .card p:last-child {
        margin-bottom: 0;
    }

    .card p {
        font-size: 1.25rem;
    }

.card--link:hover {
    transform: translateY(-2px);
    border-color: var(--gray-300);
    box-shadow: var(--shadow-lg);
}

.card__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    margin-bottom: 18px;
    border-radius: var(--radius);
    background: var(--brand-tint);
    color: var(--brand-darker);
}

    .card__icon svg {
        display: block;
    }

/* --- Legal pages (terms, privacy) ---------------------------------------
   Long-form copy: narrow measure, generous spacing, no display font. */
.legal {
    max-width: 820px;
    margin: 0 auto;
}

    /* Body copy used as an intro rather than as the whole section — e.g. under
       a section-head on /what-is-inoutboard/. The last paragraph's margin is
       zeroed, so without this the prose runs straight into whatever follows.
       Legal pages, where .legal is the last thing in its container, are
       untouched. */
    .legal:not(:last-child) {
        margin-bottom: clamp(40px, 5vw, 64px);
    }

    .legal h2 {
        margin-top: 2em;
        font-size: 1.5rem;
    }

    .legal h3 {
        margin-top: 1.6em;
        font-size: 1.25rem;
    }

    .legal h4 {
        margin-top: 1.4em;
        font-size: 1.125rem;
    }

    .legal p {
        margin-bottom: 1.1em;
        font-size: 1.0625rem;
        line-height: 1.7;
    }

    .legal ul,
    .legal ol {
        margin: 0 0 1.4em 1.4em;
        padding-left: .6em;
        list-style: disc;
    }

    .legal ol {
        list-style: decimal;
    }

        .legal li {
            margin-bottom: .55em;
            font-size: 1.0625rem;
            line-height: 1.7;
        }

    .legal a {
        text-decoration: underline;
    }

/* --- Mosaic frame --------------------------------------------------------
   A grid of small tiles — brand colours, grey placeholders and a few real
   photos — with a white panel floated over the middle so only a decorative
   border of tiles shows. Purely decorative: the grid is aria-hidden. */
.mosaic {
    position: relative;
    margin-bottom: clamp(40px, 5vw, 64px);
}

.mosaic__grid {
    display: grid;
    grid-template-columns: repeat(11, 1fr);
    gap: 10px;
}

.mosaic__tile {
    position: relative;
    aspect-ratio: 1 / 1;
    overflow: hidden;
    background: var(--gray-200);
    border-radius: var(--radius);
}

    .mosaic__tile img {
        width: 100%;
        height: 100%;
        object-fit: cover;
    }

/* Shapes */
.mosaic__tile--circ {
    border-radius: 50%;
}

.mosaic__tile--leaf {
    border-radius: 50% 12px 50% 12px;
}

/* Colours, drawn from the brand palette */
.mosaic__tile--brand {
    background: var(--brand);
}

.mosaic__tile--brand-dark {
    background: var(--brand-darker);
}

.mosaic__tile--navy {
    background: var(--navy);
}

.mosaic__tile--gold {
    background: #fbb945;
}

.mosaic__tile--green {
    background: var(--green);
}

/* The white panel that masks the middle of the grid. */
.mosaic__panel {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: min(78%, 860px);
    padding: clamp(24px, 4vw, 48px) clamp(20px, 4vw, 56px);
    background: var(--white);
    border-radius: 48px;
    text-align: center;
}

    .mosaic__panel h2 {
        margin-bottom: .15em;
        font-family: var(--font-display);
        font-size: clamp(1.75rem, 6.1vw, 4rem);
        line-height: 1.15;
        letter-spacing: 0;
        text-wrap: balance;
    }

    .mosaic__panel p {
        font-size: calc(1.275rem + 0.3vw);
        color: var(--text);
    }

/* Below tablet the tiles would be postage stamps — drop the frame and keep
   the heading on its own. */
@media (max-width: 860px) {
    .mosaic__grid {
        display: none;
    }

    .mosaic__panel {
        position: static;
        transform: none;
        width: 100%;
        padding: 0;
    }
}

/* --- Industry page hero (copy left, photo right) -------------------------
   Two even columns on desktop, stacking to one under 880px. The copy stays
   first when stacked so the h1 is still the first thing on the page. */
.industry-hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(28px, 4vw, 56px);
    align-items: center;
}

.industry-hero__copy {
    max-width: none;
    margin: 0;
    text-align: left;
}

/* Sign-up call to action under the pitch. Left-aligned with the copy on
   desktop; centred with it once the hero stacks. */
.industry-hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: clamp(24px, 3vw, 32px);
}

.industry-hero__media {
    border-radius: var(--radius-lg);
    border: 1px solid var(--gray-200);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
    background: var(--white);
}

    /* The industry photos are native 3:2, matching this column, so they need
       no cropping — they fill the frame at their own aspect ratio. */
    .industry-hero__media img {
        display: block;
        width: 100%;
        height: auto;
    }

@media (max-width: 880px) {
    .industry-hero {
        grid-template-columns: 1fr;
    }

    /* Re-centre when stacked, matching every other section head on the site. */
    .industry-hero__copy {
        text-align: center;
    }

    .industry-hero__actions {
        justify-content: center;
    }
}

/* --- Industry page headline ----------------------------------------------
   Two stacked rows: a smaller lead-in ("The status board for") over the
   industry name at full display size. Both stay inside the one <h1> so the
   heading remains a single sentence for search engines and screen readers.
   The two rows are separated by size alone — no marker highlight here, unlike
   the headlines elsewhere on the site. */
.industry-title__lead {
    display: block;
    /* Relative to the name row below, so the two rows scale together. Tune
       the .55em to change the contrast between the rows. The floor stops the
       lead-in shrinking past legibility on phones — Caveat reads noticeably
       smaller than sans at the same size. */
    font-size: max(1.25rem, .55em);
    line-height: 1.1;
}

.industry-title__name {
    display: block;
}

/* --- Industry cards (the /all-industries/ hub) ---------------------------- */
.industry-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 330px), 1fr));
    gap: 20px;
}

.industry-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    height: 100%;
    padding: 24px 26px;
    background: var(--white);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    color: var(--text);
    transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}

    .industry-card:hover {
        transform: translateY(-3px);
        border-color: var(--brand);
        box-shadow: var(--shadow-lg);
        text-decoration: none;
    }

    .industry-card svg {
        flex: none;
        color: var(--brand-darker);
    }

.industry-card__name {
    font-size: 1.125rem;
    font-weight: 600;
    line-height: 1.35;
}

/* Help hub topic cards: the same .industry-card row, with a short
   description added under the name. Scoped to --desc so the other
   .industry-card placements (the industry hub itself, and the "Where to
   go next" links on industry/feature pages) are untouched -- this
   variant is used only by /help/'s topic grid. min-width: 0 on the text
   column lets the description wrap inside the row instead of forcing the
   card wider or overflowing it. */
.industry-card--desc .industry-card__text {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.industry-card__desc {
    font-size: .875rem;
    font-weight: 400;
    line-height: 1.4;
    color: var(--gray-500);
}

/* --- Feature tiles ------------------------------------------------------- */
/* Column counts live with the variants below: the six square tiles need
   explicit counts, and the list variant sizes its tracks to content. */
.feature-grid {
    display: grid;
    gap: 20px;
}

/* Six across on a wide desktop. auto-fit used to size tracks to whatever
   space was going, which landed on a 5+1 row at ~1024px and 4+2 lower
   down. Six items divide evenly by 6, 3 and 2, so those are the counts:
   six here, three-by-two below, two-by-three on phones (480px block).
   :not(--list) keeps all of it off the compact variant other pages use. */
.feature-grid:not(.feature-grid--list) {
    grid-template-columns: repeat(6, minmax(0, 1fr));
}

/* Three-by-two. The threshold sits above 1024px deliberately, so that
   width gets three comfortable columns rather than six cramped ones. */
@media (max-width: 1100px) {
    .feature-grid:not(.feature-grid--list) {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    /* Three wide columns and a 1:1 ratio made 300px+ squares holding one
       icon and one word, so the ratio goes and a floor takes over. min-height
       rather than height: a wrapped label, a larger default font or page zoom
       grows the tile instead of spilling out of it. Icon and label stay
       centred by the flex centring on .feature-tile. */
    .feature-grid:not(.feature-grid--list) .feature-tile {
        aspect-ratio: auto;
        min-height: 150px;
        padding: 20px 16px;
    }
}

/* Square blocks, one per module. Whole tile is the link target. */
.feature-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    aspect-ratio: 1 / 1;
    padding: 16px;
    text-align: center;
    color: var(--text);
    background: var(--white);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}

    .feature-tile:hover {
        transform: translateY(-3px);
        border-color: var(--brand);
        box-shadow: var(--shadow-lg);
        text-decoration: none;
    }

/* Placeholder art slot — holds an icon now, an <img> later. */
.feature-tile__art {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 72px;
    height: 72px;
    border-radius: var(--radius);
}

    /* Overlapping shapes darken where they cross, like a printed
       two-colour illustration. */
    .feature-tile__art svg .blend {
        mix-blend-mode: multiply;
    }

    .feature-tile__art svg {
        display: block;
    }

    .feature-tile__art img {
        width: 100%;
        height: 100%;
        object-fit: contain;
    }

.feature-tile__name {
    font-size: 1.125rem;
    font-weight: 700;
    line-height: 1.25;
}

/* Wraps the name and (opt-in, list variant only) description line so they
   can stack as a column without touching the icon/arrow layout. `contents`
   keeps the wrapper invisible everywhere else -- the name renders exactly
   as if it were still a direct flex child of .feature-tile. */
.feature-tile__text {
    display: contents;
}

/* Secondary line under the name -- only rendered when a placement opts in
   (FeatureGrid's ShowDescriptions). Quieter than the name: smaller, regular
   weight, muted gray, same "quiet second row" color as .section-head__sub. */
.feature-tile__desc {
    font-size: .875rem;
    font-weight: 400;
    line-height: 1.4;
    color: var(--gray-500);
}

/* Trailing arrow — only shown in the compact list variant below. */
.feature-tile__arrow {
    display: none;
    flex: none;
    color: var(--brand-darker);
}

/* Compact list variant — slim three-across cards (icon, name, arrow),
   matching the help-center topic cards. */
.feature-grid--list {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 330px), 1fr));
}

    .feature-grid--list .feature-tile {
        flex-direction: row;
        justify-content: flex-start;
        gap: 16px;
        aspect-ratio: auto;
        padding: 18px 26px;
        text-align: left;
    }

    .feature-grid--list .feature-tile__art {
        width: 44px;
        height: 44px;
    }

        .feature-grid--list .feature-tile__art svg {
            width: 100%;
            height: 100%;
        }

    /* flex: 1 (with the column stack, when a description is present) moves
       to the wrapper so the name/description pair takes the same middle
       column the bare name used to occupy. min-width: 0 lets the text wrap
       inside that column instead of stretching the card to fit it. */
    .feature-grid--list .feature-tile__text {
        display: flex;
        flex-direction: column;
        justify-content: center;
        gap: 3px;
        flex: 1;
        min-width: 0;
    }

    .feature-grid--list .feature-tile__arrow {
        display: block;
    }

/* Phone layout for the square tiles: two columns, three rows. Below this
   width the auto-fit track above collapses to one column, which made each
   tile a full-width square -- six of those was a long scroll past the
   fold. The aspect-ratio goes and a modest min-height takes over, with the
   art and label scaled to suit. Icon stays above the label, the whole tile
   is still the link, and labels wrap rather than shrink: two lines fit the
   min-height. Colours, border, shadow, hover and focus are untouched.
   :not(--list) keeps this off the compact variant every other page uses. */
@media (max-width: 480px) {
    .feature-grid:not(.feature-grid--list) {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 12px;
    }

        .feature-grid:not(.feature-grid--list) .feature-tile {
            gap: 8px;
            aspect-ratio: auto;
            min-height: 116px;
            padding: 14px 10px;
        }

        .feature-grid:not(.feature-grid--list) .feature-tile__art {
            width: 40px;
            height: 40px;
        }

            .feature-grid:not(.feature-grid--list) .feature-tile__art svg {
                width: 100%;
                height: 100%;
            }

        .feature-grid:not(.feature-grid--list) .feature-tile__name {
            font-size: .875rem;
            line-height: 1.3;
        }
}

/* --- Feature showcase (tabs) -------------------------------------------- */
.tabs {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
    margin-bottom: 40px;
}

.tab {
    padding: 12px 20px; /* >=44px tall: comfortable touch target */
    background: var(--white);
    border: 1px solid var(--gray-300);
    border-radius: 999px;
    font-family: inherit;
    font-size: .9375rem;
    font-weight: 600;
    color: var(--text);
    cursor: pointer;
    transition: all .15s ease;
}

    .tab:hover {
        border-color: var(--brand);
        color: var(--brand-darker);
    }

    .tab[aria-selected="true"] {
        background: var(--navy);
        border-color: var(--navy);
        color: var(--white);
    }

.tabpanel[hidden] {
    display: none;
}

.showcase {
    display: grid;
    grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
    gap: clamp(28px, 4vw, 56px);
    align-items: center;
}

    .showcase h3 {
        font-size: 1.5rem;
    }

.showcase__list {
    margin-top: 20px;
}

    .showcase__list li {
        position: relative;
        padding-left: 30px;
        margin-bottom: 12px;
        font-size: 1.25rem;
    }

    .showcase__list svg {
        position: absolute;
        left: 0;
        top: 3px;
        color: var(--brand);
    }

.showcase__media {
    border-radius: var(--radius-lg);
    border: 1px solid var(--gray-200);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
    background: var(--white);
}

    .showcase__media img {
        display: block;
        width: 100%;
    }

@media (max-width: 880px) {
    .showcase {
        grid-template-columns: 1fr;
    }

    .showcase__media {
        order: -1;
    }
}

/* --- Video facade (click to load — keeps visitors on site) --------------- */
.video-wrap {
    max-width: var(--video-max);
    margin: 0 auto;
    /* White frame around the video, with an ambient shadow on all sides. */
    padding: 10px;
    background: var(--white);
    border-radius: var(--frame-radius);
    box-shadow: var(--shadow-shot);
}

    /* A plain screenshot can sit in the same white frame as a video, keeping
       its natural aspect ratio. Used on feature pages that have no demo
       video yet. */
    .video-wrap > img {
        display: block;
        width: 100%;
        height: auto;
        border-radius: var(--radius-sm);
    }

/* Two flat screenshots overlapped, after odoo.com: a back image top-left and a
   front image bottom-right, each with the flat-screenshot shadow. Everything
   is a percentage of the box, so the pair keeps its proportions at any width
   (the box is a fixed 1.7:1). Put the BACK image first in the markup and size
   its sizes= to 76% of the box, the front to 58%. The front one carries a
   little padding so a print-out that runs to the image edge does not touch
   the shadowed border. */
.shot-stack {
    position: relative;
    max-width: var(--video-max);
    margin: 0 auto;
    aspect-ratio: 1.7 / 1;
}

.shot-stack--wide {
    aspect-ratio: 2.1 / 1;
}

/* For a tall back image (the Time History form is 1.6:1): narrower back so the
   front print-out tucks over its corner without hiding the Print button. */
.shot-stack--tall {
    aspect-ratio: 1.45 / 1;
}

    .shot-stack--tall .shot-stack__img--back {
        width: 70%;
    }

.shot-stack__img {
    position: absolute;
    display: block;
    height: auto;
    box-sizing: border-box;
    /* The same white frame as every other screenshot, at 6px instead of 10px
       because these are scaled down inside a pair. */
    border: 6px solid var(--white);
    background: var(--white);
    border-radius: calc(var(--radius-sm) + 6px);
    box-shadow: var(--shadow-shot);
}

.shot-stack__img--back {
    left: 0;
    top: 0;
    width: 76%;
}

.shot-stack__img--front {
    right: 0;
    bottom: 0;
    width: 58%;
    box-sizing: border-box;
    padding: 1.5%;
}

/* 2:1, not 16:9 — every source video on Vimeo is 1920x960. Matching the box
   to the footage means the poster is never cropped and the player never
   letterboxes, so nothing shifts when the iframe swaps in. */
.video {
    position: relative;
    aspect-ratio: 2 / 1;
    border-radius: 0;
    overflow: hidden;
    background: var(--navy);
}

    /* For a video exported at 16:9 (the October 2026 status board,
       calendar, dashboard, resources, messages, reports, alerts, mobile, setup and status update recordings and the home page introduction, Vimeo 1234217657, 1234446450, 1234469971, 1234479849, 1234491166, 1234502094, 1234515052, 1234520532, 1234528466, 1234535708 and 1234852323). In the 2:1 frame the player would pillarbox it with
       black down both sides; this frame matches the file, so the poster and
       the playing video line up with no jump on Play. */
    .video--16x9 {
        aspect-ratio: 16 / 9;
    }

    .video img,
    .video iframe {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        border: 0;
        object-fit: cover;
    }

.video__btn {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    padding: 0;
    background: rgba(21, 26, 38, .28);
    border: 0;
    cursor: pointer;
    transition: background-color .2s ease;
}

    .video__btn:hover {
        background: rgba(21, 26, 38, .12);
    }

    /* This button is inset:0 inside .video, which clips its overflow, so the
       global ring -- drawn 2px outside the button -- lands entirely in the
       clipped region and nothing shows at all. Same two tones, turned inward:
       a white band hugging the edge with the dark ring just inside it, both
       within the clip. Two tones matter more here than anywhere else, since
       what sits behind is a poster photo rather than a known flat colour. */
    .video__btn:focus-visible {
        outline-offset: -5px;
        box-shadow: inset 0 0 0 2px var(--focus-ring-inner);
    }

    /* Styles EVERY span in the button, the .sr-only label included -- this
       selector is (0,1,1) and .sr-only is (0,1,0), so the label loses its 1px
       box and gets the 72px circle too. It stays hidden on position, overflow
       and clip alone. Leave that alone: giving .sr-only its size back here
       would put a second white circle beside the play control. */
    .video__btn span {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 72px;
        height: 72px;
        border-radius: 50%;
        background: var(--white);
        color: var(--brand-darker);
        box-shadow: var(--shadow-xl);
        transition: transform .2s ease;
    }

    .video__btn:hover span {
        transform: scale(1.06);
    }

    /* Outlined play glyph: a blue triangle with a dark keyline, rather than
       the solid single-colour shape this used to be.

       Set here rather than on each <svg> because the same button markup is
       repeated 19 times across 13 pages. CSS beats the fill="currentColor"
       presentation attribute in the cascade, so one rule restyles every play
       button and there is no per-page copy of the glyph to keep in step. */
    .video__btn svg {
        width: 34px;
        height: 34px;
        fill: var(--brand);
        stroke: var(--navy);
        /* User units inside the 24x24 viewBox, so the keyline scales with the
           glyph instead of thinning out as the button grows. */
        stroke-width: 2;
        /* Rounds the apex and both back corners, which is what gives the mark
           its soft look. It is also load-bearing: a mitred join at this
           stroke width spikes the point well past the triangle. */
        stroke-linejoin: round;
        /* Optical centring -- a triangle carries its mass left of its bounding
           box, so it has to sit right of true centre to look centred. */
        margin-left: 4px;
    }

/* Tutorial rows: one video per row with its summary alongside, alternating
   sides down the page. A three-across grid left each player around 370px —
   too small to actually follow a walkthrough — so these get a wider track
   than .feature-split gives its screenshots. */
.video-split {
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    gap: clamp(28px, 4vw, 56px);
    align-items: center;
    text-align: left;
}

    .video-split + .video-split {
        margin-top: clamp(40px, 6vw, 80px);
    }

    /* The media column is a plain block wrapper, not the grid item itself:
       .video-wrap has auto side margins, which suppress grid stretch and
       collapse the aspect-ratio box to zero width. */
    .video-split__media {
        width: 100%;
    }

    /* The industry-page workflow shots are app screenshots already sitting in
       an angled monitor frame, so they get no card treatment — same reasoning
       as .feature-split__media. A white .video-wrap card around an
       already-framed monitor is a frame inside a frame. These sit straight on
       the section background instead. */
    .video-split__media > img {
        display: block;
        width: 100%;
        height: auto;
    }

    /* Opt-in for a flat screenshot (not an angled mockup). Add class="shot" to
       the <img>; the mockups carry their own baked-in shadow and must not get
       this, or it outlines their transparent rectangle. */
    .video-split__media > img.shot {
        box-sizing: border-box;
        border: 10px solid var(--white);
        border-radius: var(--frame-radius);
        background: var(--white);
        box-shadow: var(--shadow-shot);
    }

    /* Phone screenshots are portrait (720x1413). Left at the media column's
       full width one renders past 1200px tall and towers over the steps
       beside it, so the narrow track goes to the phone and the wide one to
       the copy, with a cap that keeps the frame near its text in height.
       The cap survives the stack below 860px, where a full-width phone would
       be even more out of proportion. */
    .video-split--portrait {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr);
    }

    .video-split--portrait .video-split__media {
        max-width: 300px;
        margin-inline: auto;
    }

    /* The phone images are transparent cut-outs of an iPhone frame with the
       screenshot inside, so the shadow follows the phone's outline (filter,
       not box-shadow, which would draw a rectangle). Two layers in the same
       neutral blue-grey as --shadow-shot. */
    .video-split--portrait .video-split__media > img {
        filter: drop-shadow(0 0 12px rgba(16, 24, 40, .14)) drop-shadow(0 12px 16px rgba(16, 24, 40, .16));
    }

    /* Portrait rows alternate down the page like the tutorial rows do.
       --reverse already moves the media to column 2; the tracks have to swap
       with it so the phone keeps the narrow one and the copy the wide one. */
    .video-split--portrait.video-split--reverse {
        grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    }

    /* A check-list inside one of these rows has half the width it was built
       for, so it runs as a single column and loses the top margin it uses
       when it follows a section-head. Same treatment as .feature-split. */
    .video-split__body .check-list {
        grid-template-columns: 1fr;
        margin-top: 0;
    }

    /* h2 on the feature page (nothing between it and the hero h1); h3 was
       for the help page's "Watch and learn", removed 11 October 2026. Same
       size either way — the heading labels one video, it is not a section
       banner. */
    .video-split__body h2,
    .video-split__body h3 {
        margin: 0 0 12px;
        font-size: 1.5rem;
    }

    /* Quiet runtime line for a video. One placement everywhere on the site:
       immediately above the player, outside the poster, left edge flush with
       the player's left edge, --video-label-gap between the two.

       It gets .video-wrap's own box to achieve that -- same --video-max cap,
       same centring -- so the two line up wherever the column is wider than
       the cap, and both simply fill the column where it is narrower (the
       split-column sections on /help/ and /features/set-up/, and every width
       below 880px). A context that narrows .video-wrap has to narrow this the
       same way; .faq details is the one that does.

       Kept as its own class rather than styling .video-split__body p, since
       that shared component's h2/h3 + <p> pattern is also used by the
       industry and feature pages for unrelated body copy. */
    .video-split__duration {
        max-width: var(--video-max);
        margin: 0 auto var(--video-label-gap);
        font-size: .875rem;
        color: var(--gray-500);
        text-align: left;
    }

    .video-split__body p:last-child {
        margin-bottom: 0;
    }

    /* Even rows flip the media to the right. The wide track has to move with
       it, or the flipped video comes out a third narrower than its neighbours.
       Placement is explicit rather than reordering the DOM, so the video keeps
       leading its summary for screen readers and for the stacked layout. */
    .video-split--reverse {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr);
    }

    .video-split--reverse .video-split__media {
        grid-column: 2;
        grid-row: 1;
    }

    .video-split--reverse .video-split__body {
        grid-column: 1;
        grid-row: 1;
    }

@media (max-width: 860px) {
    .video-split {
        grid-template-columns: 1fr;
    }

        /* Two classes outrank the single-class rule above, so the combined
           portrait-reverse row needs its own stacking override or it stays
           side by side on phones. */
        .video-split--portrait.video-split--reverse {
            grid-template-columns: 1fr;
        }

        .video-split--reverse .video-split__media,
        .video-split--reverse .video-split__body {
            grid-column: 1;
            grid-row: auto;
        }
}

/* --- Scout (/features/automation/) ---------------------------------------
   Scout's art is a transparent cut-out of a drawn dog, not a phone frame, so
   the portrait rows keep their narrow track but drop the phone's outline
   shadow. Narrower than the phone's 300px too, so he stays a companion to
   the copy rather than the subject of the row. */
/* Hero: copy left, Scout right, so the headline that introduces him and the
   picture of him are seen together. Below 860px he moves above the copy,
   smaller, and the copy goes back to the centred section-head treatment.
   The image comes first in the DOM for that stacked order; on desktop it
   is placed in the second column instead. */
.scout-intro {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 240px;
    gap: clamp(28px, 4vw, 56px);
    align-items: center;
    text-align: left;
}

    .scout-intro__img {
        grid-column: 2;
        grid-row: 1;
        display: block;
        width: 240px;
        height: auto;
    }

    .scout-intro__text {
        grid-column: 1;
        grid-row: 1;
    }

        .scout-intro__text p:last-child {
            margin-bottom: 0;
        }

@media (max-width: 860px) {
    .scout-intro {
        grid-template-columns: 1fr;
        gap: 20px;
        text-align: center;
    }

        .scout-intro__img,
        .scout-intro__text {
            grid-column: 1;
            grid-row: auto;
        }

        .scout-intro__img {
            width: 150px;
            margin: 0 auto;
        }
}

.video-split--scout .video-split__media {
    max-width: 240px;
}

    .video-split--scout .video-split__media > img {
        filter: none;
    }

/* --- Alert timeline (/features/alerts/) -----------------------------------
   The four past-due alerts in the order they go out, added 13 Oct 2026 at
   Lisa's request. Four columns joined by a line on desktop; below 860px the
   steps stack and the line runs down the left. The two steps aimed at the
   user's managers take the navy marker, so the hand-off from "the person is
   told" to "someone else is told" reads at a glance. */
.alert-timeline {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 24px;
    margin: 32px 0 0;
    padding: 0;
    list-style: none;
    counter-reset: alert-step;
}

    .alert-timeline li {
        position: relative;
        padding-top: 56px;
        text-align: center;
        counter-increment: alert-step;
    }

        .alert-timeline li::before {
            content: counter(alert-step);
            position: absolute;
            top: 0;
            left: 50%;
            z-index: 1;
            display: grid;
            place-items: center;
            width: 40px;
            height: 40px;
            margin-left: -20px;
            border-radius: 50%;
            background: var(--brand-darker);
            color: var(--white);
            font-weight: 700;
        }

        .alert-timeline li::after {
            content: "";
            position: absolute;
            top: 19px;
            left: calc(50% + 20px);
            width: calc(100% - 16px);
            height: 2px;
            background: var(--gray-300);
        }

        .alert-timeline li:last-child::after {
            display: none;
        }

        .alert-timeline li.alert-timeline__manager::before {
            background: var(--navy);
        }

    .alert-timeline__when {
        display: block;
        margin-bottom: 4px;
        color: var(--brand-darker);
        font-size: .8125rem;
        font-weight: 700;
        letter-spacing: .04em;
        text-transform: uppercase;
    }

    .alert-timeline__manager .alert-timeline__when {
        color: var(--navy);
    }

    .alert-timeline__who {
        display: block;
        color: var(--gray-900);
        font-size: 1.125rem;
        line-height: 1.4;
    }

.alert-timeline__note {
    max-width: var(--container-narrow);
    margin: 28px auto 40px;
    color: var(--gray-700);
    text-align: center;
}

@media (max-width: 860px) {
    .alert-timeline {
        grid-template-columns: 1fr;
    }

        .alert-timeline li {
            min-height: 40px;
            padding: 8px 0 0 56px;
            text-align: left;
        }

            .alert-timeline li::before {
                left: 0;
                margin-left: 0;
            }

            .alert-timeline li::after {
                top: 40px;
                left: 19px;
                width: 2px;
                height: calc(100% - 16px);
            }

    .alert-timeline__note {
        text-align: left;
    }
}

/* --- Use cases ----------------------------------------------------------- */
.usecase {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    padding: 0;
}

    .usecase img {
        display: block;
        width: 100%;
        aspect-ratio: 16 / 10;
        object-fit: cover;
    }

.usecase__body {
    padding: 24px 24px 28px;
}

    .usecase__body h3 {
        font-size: 1.5rem;
    }

.usecase__more {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 14px;
    font-size: .9375rem;
    font-weight: 600;
    color: var(--brand-darker);
}

/* Standalone version of the same link, used to close a section. It sits on its
   own rather than inside a card, so it carries a little more weight. */
.usecase__more--lg {
    gap: 8px;
    font-size: 1.125rem;
}

    .usecase__more--lg svg {
        width: 18px;
        height: 18px;
    }

.card--link:hover .usecase__more {
    text-decoration: underline;
}

/* The home page industry links name their industry in full ("Explore
   InOutBoard for engineering, construction & architecture"), so they wrap to
   two lines inside a card. Flex is the wrong layout for that: the label and
   the arrow are separate flex items, so a wrapped label takes up the whole
   width of the card and strands the arrow out in the whitespace at the far
   right, centred between the two lines -- and once the label is long enough,
   the arrow gets shrunk out of shape to make room for it.

   Laying the link out as ordinary inline text instead puts the arrow after the
   last word, the way it already sits on the one-line labels, and lets the line
   break fall wherever it needs to. Scoped to .home-industries: the About page
   cards and the "See all industries" link below still carry the short label
   the flex version was written for. */
.home-industries .usecase__more {
    display: inline-block;
}

    /* gap only applies inside a flex container, so the arrow spaces itself. */
    .home-industries .usecase__more svg {
        margin-left: 6px;
        vertical-align: middle;
    }

/* Compact phone layout for the home page industry cards. The 16:10 banner
   plus a full-width body made each card very tall, and six of them a long
   scroll; here a cropped 72px square sits beside the title, with the
   description and link across the full width underneath.

   .usecase__body becomes display: contents so its h3, p and link are grid
   items of the card itself -- that lets the title share a row with the
   thumbnail while the rest spans both columns, without restyling the
   markup. The body carries the padding normally, so it moves to the card.

   Rows are auto, so a title that wraps to three lines grows the card
   instead of being clipped. Scoped to .home-industries: .usecase is also
   used on the About page. */
@media (max-width: 480px) {
    .home-industries .usecase {
        display: grid;
        grid-template-columns: 72px minmax(0, 1fr);
        align-items: center;
        column-gap: 14px;
        padding: 16px;
    }

    .home-industries .usecase__body {
        display: contents;
    }

    .home-industries .usecase img {
        grid-area: 1 / 1;
        width: 72px;
        height: 72px;
        aspect-ratio: 1 / 1;
        border-radius: var(--radius);
    }

    .home-industries .usecase__body h3 {
        grid-area: 1 / 2;
        margin: 0;
        font-size: 1.125rem;
        line-height: 1.3;
    }

    .home-industries .usecase__body p {
        grid-area: 2 / 1 / 3 / -1;
        margin: 14px 0 0;
    }

    .home-industries .usecase__more {
        grid-area: 3 / 1 / 4 / -1;
        margin-top: 12px;
    }
}

/* --- Video transcript ----------------------------------------------------
   Disclosure under the home page demo video. The transcript lives in the
   server-rendered markup rather than being fetched on open, so it is in the
   page for search engines and for anyone reading with the disclosure shut.

   Native <details>/<summary> does the whole job: pointer and keyboard
   toggling (Enter and Space), and the correct expanded/collapsed state for
   assistive technology, with no JS. That matters here -- the video itself is
   click-to-load from site.js, so if that script never runs the transcript is
   still the one way to get at the content.

   Same disclosure pattern as .faq: default marker off, custom chevron that
   flips when open. Quieter than the FAQ though -- this is a utility control
   under a video, not a section of its own -- so it takes the supporting-text
   size and the link colour instead of the FAQ's 1.25rem headline weight.
   Keyboard focus is the global :focus-visible outline, which lands on the
   summary because that is the focusable element. The chevron transition is
   already neutralised by the global prefers-reduced-motion block. */

/* Dated-content note for a video whose footage no longer matches the app.
   Placed immediately before the player on both pages that embed the clip, so
   it is read before watching rather than after -- and before the transcript,
   which quotes the same outdated step. Takes .video-wrap's width token so it
   lines up with the player it belongs to. */
.video-note {
    max-width: var(--video-max);
    margin: 0 auto 16px;
    padding: 12px 16px;
    border-left: 4px solid var(--brand);
    border-radius: var(--radius-sm);
    background: var(--brand-tint);
    color: var(--gray-700);
    font-size: .9375rem;
    line-height: 1.55;
    text-align: left;
}


.transcript {
    /* Same width token as .video-wrap, and centred the same way, so the
       expanded transcript sits in exactly the video's column -- matching
       outer edges, and matching automatically if that width ever changes.
       Below the token the .container padding takes over for both, so the
       transcript keeps the video's side gutters on a phone. */
    max-width: var(--video-max);
    margin: 22px auto 0;
    /* Centres the summary, which is inline-flex and so centres as an inline
       box. Deliberately not a full-width flex summary: that would stretch the
       hit area and the focus ring across all 880px, and the ring reads far
       better hugging the label. The body undoes this -- centred prose is
       harder to read, and only the control was meant to move. */
    text-align: center;
}

    .transcript summary {
        display: inline-flex;
        align-items: center;
        gap: 9px;
        padding: 6px 0;
        font-size: 1rem;
        font-weight: 600;
        color: var(--brand-darker);
        cursor: pointer;
        /* Both needed to drop the native triangle: list-style for standards
           browsers, the pseudo-element for older WebKit. */
        list-style: none;
    }

        .transcript summary::-webkit-details-marker {
            display: none;
        }

        .transcript summary::after {
            content: "";
            flex: none;
            width: 9px;
            height: 9px;
            border-right: 2px solid currentColor;
            border-bottom: 2px solid currentColor;
            transform: rotate(45deg) translateY(-2px);
            transition: transform .2s ease;
        }

    .transcript[open] summary::after {
        transform: rotate(225deg) translateY(-2px);
    }

    .transcript summary:hover {
        text-decoration: underline;
    }

    .transcript__body {
        padding: 4px 0 2px;
        text-align: left;
    }

        /* Body copy scale of the page's supporting text. No measure cap: the
           paragraphs are meant to fill the video's column so the expanded
           transcript lines up with it on both edges. A 70ch cap used to sit
           here and left the text ending ~130px short of the video's right
           edge, which read as a misalignment rather than as a reading
           measure. Lines do run long at the full width -- that is the
           trade-off for matching the video, and it only applies to a
           transcript someone has chosen to open. */
        .transcript__body p {
            margin: 0 0 14px;
            font-size: 1.0625rem;
            line-height: 1.7;
            color: var(--text);
        }

        .transcript__body p:last-child {
            margin-bottom: 0;
        }

/* --- People (About page) --------------------------------------------------
   "The people behind InOutBoard": a short intro and one card per person, on
   the same 820px measure as the story text above it so the two read as one
   column. Photo, then name, role and a short bio. No profile links: personal
   LinkedIn links were taken off at the owner's request, 3 October 2026.

   One full-width card per person, photo on the left, text left-aligned:
   with a bio paragraph in each card, three narrow centred columns made for
   short, ragged centred lines that were hard to read. Under 480px the
   photo moves above the text.

   The photo is a 160px circle. It started at 88px, the size of the featured
   testimonial avatar, and was enlarged the same day at the owner's request:
   at 88px the faces read as icons rather than portraits. The files
   in /img/people/ are already cropped square around the face, so
   object-fit:cover only guards against a wrong-shaped replacement. */
.people {
    max-width: 820px;
    margin: clamp(40px, 5vw, 56px) auto 0;
}

    .people .people__title {
        margin: 0 0 .4em;
        font-size: 1.5rem;
    }

    .people .people__intro {
        margin-bottom: 24px;
    }

.people__list {
    display: grid;
    gap: 24px;
}

.person {
    display: flex;
    align-items: flex-start;
    gap: 32px;
}

@media (max-width: 480px) {
    .person {
        flex-direction: column;
        gap: 16px;
    }
}

.person__photo {
    flex: none;
    width: 160px;
    height: 160px;
    border-radius: 50%;
    object-fit: cover;
    background: var(--gray-200);
}

    .person .person__name {
        margin: 0 0 2px;
        font-size: 1.25rem;
    }

    .person p.person__role {
        margin: 0;
        font-size: 1rem;
        color: var(--gray-600);
    }

    /* The reassurance line under the cards ("Small doesn't mean fragile..."):
       ordinary body copy, spaced off the last card. */
    .people .people__note {
        margin: 24px 0 0;
    }

    /* Body size, not .card p's 1.25rem: three paragraphs at card-heading
       scale overpowered the names above them. */
    .person p.person__bio {
        margin: 10px 0 0;
        font-size: 1.0625rem;
        line-height: 1.6;
    }

/* --- Testimonials -------------------------------------------------------- */
.quote {
    display: flex;
    flex-direction: column;
    padding: 28px;
    background: var(--white);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

    .quote blockquote {
        margin: 0 0 20px;
        font-size: 1.25rem;
        line-height: 1.55;
        color: var(--text);
    }

    .quote figcaption {
        display: flex;
        align-items: center;
        gap: 12px;
        margin-top: auto;
    }

    .quote img {
        width: 48px;
        height: 48px;
        border-radius: 50%;
        object-fit: cover;
        background: var(--gray-100);
    }

.quote__name {
    font-weight: 600;
    color: var(--text);
    font-size: .9375rem;
}

.quote__org {
    font-size: .875rem;
    color: var(--text);
}

.quote .stars {
    margin-bottom: 14px;
}

/* Single featured testimonial: light card, quote copy on the left and the
   attribution stacked on the right, with an oversized quote mark straddling
   the top edge. */
.quote--featured {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.9fr) minmax(0, 1fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
  max-width: 1040px;
  margin: 46px auto 0;
  padding: clamp(36px, 4vw, 56px);
  background: var(--gray-100);
  border: 0;
  border-radius: var(--radius-xl);
  box-shadow: none;
  text-align: left;
}

/* Layered opening quote: orange copy offset behind a black one. */
.quote__mark {
  position: absolute;
  top: -.34em;
  left: clamp(28px, 3.5vw, 52px);
  font-family: Georgia, "Times New Roman", serif;
  font-size: 7.5rem;
  font-weight: 800;
  line-height: 1;
  color: var(--text);
}
.quote__mark-back {
  position: absolute;
  top: .055em;
  left: .085em;
  color: #fbb945;
}

.quote--featured blockquote {
  margin: 0;
  font-size: clamp(1.25rem, 1.9vw, 1.625rem);
  line-height: 1.5;
  font-weight: 600;
  color: var(--text);
}

/* Attribution column: avatar, then name and organisation. */
.quote--featured figcaption {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  margin: 0;
  text-align: center;
}
.quote--featured img.quote__avatar {
  width: 88px;
  height: 88px;
  margin-bottom: 10px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--gray-200);
}
.quote--featured .quote__name {
  font-size: 1.0625rem;
  font-weight: 700;
}
.quote--featured .quote__org {
  font-size: .9375rem;
  color: var(--gray-600);
}

@media (max-width: 720px) {
  .quote--featured {
    grid-template-columns: 1fr;
  }
  .quote--featured figcaption {
    align-items: flex-start;
    text-align: left;
  }
}

/* --- Pricing preview ----------------------------------------------------- */
.price-card {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: 32px 28px;
    background: var(--white);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}

.price-card--featured {
    border-color: var(--brand);
    border-width: 2px;
    box-shadow: var(--shadow-lg);
}

.price-card__badge {
    position: absolute;
    top: -13px;
    left: 50%;
    transform: translateX(-50%);
    padding: 4px 14px;
    border-radius: 999px;
    background: var(--brand);
    color: var(--white);
    font-size: .75rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    white-space: nowrap;
}

.price-card__seats {
    font-size: 1.375rem;
    font-weight: 700;
    color: var(--text);
}

.price-card__for {
    font-size: .875rem;
    color: var(--text);
    margin-bottom: 20px;
}

.price-card__amount {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin-bottom: 4px;
}

    .price-card__amount b {
        font-size: 2.75rem;
        font-weight: 700;
        color: var(--text);
        letter-spacing: -.03em;
        line-height: 1;
    }

    .price-card__amount span {
        font-size: .9375rem;
        color: var(--text);
    }

.price-card__note {
    font-size: .8125rem;
    color: var(--text);
    margin-bottom: 24px;
}

.price-card .btn {
    margin-top: auto;
}

.grid--pricing {
    max-width: 1000px;
    margin-inline: auto;
}

.price-card__list {
    margin: 24px 0 0;
}

    .price-card__list li {
        position: relative;
        padding-left: 28px;
        margin-bottom: 10px;
        font-size: .9375rem;
    }

    .price-card__list svg {
        position: absolute;
        left: 0;
        top: 4px;
        color: var(--green);
    }

.price-card__list--inline {
    display: flex;
    flex-wrap: wrap;
    gap: 12px 32px;
    justify-content: center;
    margin-top: 32px;
}

.pricing-more {
    text-align: center;
    margin-top: 28px;
}

    .pricing-more svg {
        vertical-align: -2px;
    }

/* License table on /pricing/ — every tier, monthly and annual. */
.price-table {
    width: 100%;
    max-width: 720px;
    margin: 0 auto;
    border-collapse: collapse;
}

    .price-table th,
    .price-table td {
        padding: 14px 16px;
        border-bottom: 1px solid var(--gray-200);
        text-align: left;
    }

    /* Column headers only -- scoped to thead so the row headers below
       (the "10 users" cells, marked up as th scope="row" for AT) do not
       inherit this all-caps treatment and keep reading like data cells. */
    .price-table thead th {
        font-size: .8125rem;
        font-weight: 700;
        letter-spacing: .06em;
        text-transform: uppercase;
        color: var(--text);
    }

    .price-table th:nth-child(n+2),
    .price-table td:nth-child(n+2) {
        text-align: right;
        font-variant-numeric: tabular-nums;
    }

    /* Row headers: same weight/colour the first column had as a plain <td>,
       so marking it up for accessibility changes no pixel. Left-aligned and
       normal case already come from the shared rule above -- this only
       replaces what nth-child(n+2) and thead th no longer reach. */
    .price-table tbody th {
        font-weight: 600;
        color: var(--text);
    }

    /* First-run caption. Sits like a quiet label above the header row --
       same small caps/tracking as the headers so it reads as part of the
       table's own type system rather than a heading, but lighter weight and
       muted so it stays secondary to the numbers. */
    .price-table caption {
        margin-bottom: 10px;
        font-size: .8125rem;
        font-weight: 600;
        letter-spacing: .06em;
        text-transform: uppercase;
        color: var(--gray-500);
        text-align: left;
    }

    /* Below 480px the four columns, trial button included, have to fit a
       phone without scrolling, or the button that is the point of the row
       starts off-screen. Tighter gutters, flush outer edges, and type one
       step down fit it in 312px, a 360px phone less the page gutters. */
    @media (max-width: 480px) {
        .price-table {
            font-size: .9375rem;
        }

            .price-table th,
            .price-table td {
                padding: 12px 4px;
                white-space: nowrap;
            }

                .price-table th:first-child,
                .price-table td:first-child {
                    padding-left: 0;
                }

                .price-table th:last-child,
                .price-table td:last-child {
                    padding-right: 0;
                }

            .price-table thead th {
                font-size: .75rem;
                letter-spacing: .02em;
            }

            .price-table .btn--sm {
                padding: 6px 10px;
            }
    }

/* --- Trust seal ----------------------------------------------------------
   Third-party validation badge (SecurityMetrics, on /security/). Capped by
   width rather than left at natural size: the supplied asset is far larger
   than it needs to be, and a seal that shouts undercuts the point. */
.trust-seal {
    margin: 0 0 1.4em;
}

    .trust-seal img {
        display: block;
        width: 100%;
        max-width: 220px;
        height: auto;
    }

/* --- Data table ----------------------------------------------------------
   Same rhythm as .price-table, but every column stays left-aligned: this one
   carries prose (the sub-processor list on /security/), not figures. */
.data-table {
    width: 100%;
    margin: 0 0 1.4em;
    border-collapse: collapse;
    font-size: 1rem;
}

    .data-table th,
    .data-table td {
        padding: 12px 16px 12px 0;
        border-bottom: 1px solid var(--gray-200);
        text-align: left;
        vertical-align: top;
    }

    .data-table th {
        font-size: .8125rem;
        font-weight: 700;
        letter-spacing: .06em;
        text-transform: uppercase;
        color: var(--text);
    }

    .data-table td:first-child {
        font-weight: 600;
        color: var(--text);
    }

/* --- Responsive table wrapper -------------------------------------------
   The three data tables (licences on /pricing/, sub-processors on /security/,
   known barriers on /accessibility/) have a min-content width wider than a
   320px viewport, which was pushing the whole page sideways. The wrapper
   takes that horizontal scroll so the page never does. Desktop is unchanged:
   with room to spare, overflow-x: auto shows nothing at all.

   The table markup stays inside untouched, so thead / th[scope] semantics
   and the existing .price-table and .data-table rules still apply.

   The scrolling cue is the standard four-layer scrolling-shadow trick. The
   two opaque covers are attached `local` so they travel with the content and
   mask the shadow at whichever edge is flush; the two shadows are attached
   `scroll` so they stay pinned to the box. When the table fits, both covers
   rest over both shadows and nothing shows -- so the cue appears only when
   there is more to reach, with no JS needed to measure anything. */
.table-scroll {
    /* Covers have to match the section behind them or they smear. */
    --table-cue: var(--white);
    overflow-x: auto;
    background:
        linear-gradient(to right, var(--table-cue) 40%, transparent) left center,
        linear-gradient(to left, var(--table-cue) 40%, transparent) right center,
        radial-gradient(farthest-side at 0 50%, rgba(16, 24, 40, .20), rgba(16, 24, 40, 0)) left center,
        radial-gradient(farthest-side at 100% 50%, rgba(16, 24, 40, .20), rgba(16, 24, 40, 0)) right center;
    background-repeat: no-repeat;
    background-size: 44px 100%, 44px 100%, 14px 100%, 14px 100%;
    background-attachment: local, local, scroll, scroll;
}

    .section--tint .table-scroll {
        --table-cue: var(--gray-50);
    }

    /* A scroll container is only useful to a keyboard user if they can see
       they have landed on it. This used to restate a darker blue because the
       global ring was low-contrast cyan; the global ring now carries its own
       contrast on every background, so there is nothing left to override. */

/* --- FAQ ----------------------------------------------------------------- */
.faq {
    max-width: var(--container-narrow);
    margin: 0 auto;
}

    /* An FAQ straight under a screenshot or video sat flush against it: the
       first question was only its own 22px padding below the frame, inside
       the frame's drop shadow. Same gap as a section-head leaves above its
       content (feature pages: dashboard, calendar, set-up, status board,
       alerts, mobile and reports; also /emergency-roll-call/). */
    .video-wrap + .faq,
    .video-split + .faq,
    .shot-stack + .faq {
        margin-top: clamp(40px, 5vw, 64px);
    }

    .faq details {
        border-bottom: 1px solid var(--gray-200);
    }

    .faq summary {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 20px;
        padding: 22px 0;
        font-size: 1.25rem;
        font-weight: 600;
        color: var(--text);
        cursor: pointer;
        list-style: none;
    }

        .faq summary::-webkit-details-marker {
            display: none;
        }

        .faq summary::after {
            content: "";
            flex: none;
            width: 11px;
            height: 11px;
            border-right: 2px solid var(--gray-400);
            border-bottom: 2px solid var(--gray-400);
            transform: rotate(45deg) translateY(-3px);
            transition: transform .2s ease;
        }

    .faq details[open] summary::after {
        transform: rotate(225deg) translateY(-3px);
    }

    .faq details p {
        padding: 0 0 22px;
        font-size: 1.25rem;
        max-width: 70ch;
    }

    /* Rich article bodies on the help topic pages: numbered steps,
       sub-headings, and inline demo videos. The global reset strips list
       styling, so it is restored here (same approach as .legal). */
    .faq details ul,
    .faq details ol {
        margin: 0 0 22px 1.4em;
        padding-left: .6em;
        list-style: disc;
        max-width: 70ch;
    }

    .faq details ol {
        list-style: decimal;
    }

    .faq details li {
        margin-bottom: 10px;
        font-size: 1.25rem;
        line-height: 1.6;
    }

    .faq details h3 {
        margin: 0 0 12px;
        font-size: 1.25rem;
    }

    /* Steps with a picture each (the iPhone and Android Home Screen steps
       on /help/mobile/, since 11 October 2026). Each step is its text over a
       phone image -- a screenshot (iPhone) or an illustration (Android) in a
       phone frame with what to tap ringed, one transparent WebP like the
       phone on /features/mobile/.
       Three to a row in the 900px answer column, fewer as it narrows, one on
       a phone. Subgrid lines the phones up along a row however long the
       text above them runs. The numbers are drawn as circles, so the list's
       own markers are off; role="list" on the <ol> keeps it a list for
       Safari's VoiceOver. --brand-darker, not --brand, under the white
       numbers, for contrast. */
    .faq details ol.phone-steps {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
        gap: 36px 28px;
        max-width: none;
        margin: 8px 0 32px;
        padding: 0;
        list-style: none;
        counter-reset: phone-step;
    }

        .faq details .phone-steps > li {
            display: grid;
            grid-template-rows: subgrid;
            grid-row: span 2;
            gap: 16px;
            margin: 0;
            counter-increment: phone-step;
        }

        .faq details .phone-steps p {
            position: relative;
            max-width: none;
            padding: 3px 0 0 46px;
            font-size: 1.125rem;
            line-height: 1.5;
        }

            .faq details .phone-steps p::before {
                content: counter(phone-step);
                position: absolute;
                top: 0;
                left: 0;
                display: grid;
                place-items: center;
                width: 32px;
                height: 32px;
                border-radius: 50%;
                background: var(--brand-darker);
                color: #fff;
                font-size: 1rem;
                font-weight: 700;
            }

        /* Same two-layer drop shadow as the cut-out phones in
           .video-split--portrait, so the shadow follows the phone. */
        .faq details .phone-steps img {
            justify-self: center;
            width: 100%;
            max-width: 240px;
            height: auto;
            filter: drop-shadow(0 0 12px rgba(16, 24, 40, .14)) drop-shadow(0 12px 16px rgba(16, 24, 40, .16));
        }

    .faq details .video-wrap {
        max-width: 640px;
        margin: 0 0 22px;
    }

    /* A video's runtime line and its transcript disclosure can now sit
       inside a FAQ answer (see /help/free-trial/). Several rules above
       target any <details>/summary/p under .faq, unscoped -- .faq summary
       and .transcript summary tie on specificity and .faq's sits later in
       this file, so it would otherwise win; .faq details p outranks
       .transcript__body p outright; .video-split__duration has no class of
       its own to compete with .faq details p either. Restate the runtime
       line's and transcript's own look here, scoped only to this nesting,
       so no other .faq page or the home-page/help-page transcripts are
       affected. */
    .faq details .video-split__duration {
        padding: 0;
        max-width: 640px;
        margin: 0 0 var(--video-label-gap);
        font-size: .875rem;
        color: var(--gray-500);
        text-align: left;
    }

    /* Same collision as the runtime line and transcript: .faq details p
       outranks .video-note, so the note's own look is restated for this
       nesting -- at the 640px video width, flush left like the player. */
    .faq details .video-note {
        max-width: 640px;
        margin-inline: 0;
        padding: 12px 16px;
        font-size: .9375rem;
    }

    .faq details .transcript {
        max-width: 640px;
        /* The base rule centres the transcript with auto side margins, which
           lines it up with a centred video. The video above is flush left in
           this nesting, so the auto margins have to go or the transcript
           lands 130px to its right instead of in its column. */
        margin-inline: 0;
    }

    .faq details .transcript summary {
        display: inline-flex;
        justify-content: flex-start;
        align-items: center;
        gap: 9px;
        padding: 6px 0;
        font-size: 1rem;
        font-weight: 600;
        color: var(--brand-darker);
    }

    .faq details .transcript summary::after {
        width: 9px;
        height: 9px;
        border-right: 2px solid currentColor;
        border-bottom: 2px solid currentColor;
        transform: rotate(45deg) translateY(-2px);
    }

    .faq details .transcript[open] summary::after {
        transform: rotate(225deg) translateY(-2px);
    }

    .faq details .transcript__body p {
        padding: 0;
        max-width: none;
        font-size: 1.0625rem;
    }

/* --- Help topic question headings -----------------------------------------
   Each top-level FAQ question on the /help/ topic pages carries an <h2> inside
   its <summary>, so the questions appear in the document outline between the
   page h1 and the h3 sub-headings inside the answers. The h2 must not change
   how the summary looks: `font: inherit` hands back the summary's own 1.25rem
   /600, and letter-spacing has to be listed separately because it is not part
   of the font shorthand.

   Scoped `.faq > details > summary` on purpose. The nested transcript
   disclosures are controls, not article headings, and carry no h2 -- this must
   never start matching them. */
.faq > details > summary h2 {
    font: inherit;
    letter-spacing: inherit;
    color: inherit;
    margin: 0;
    /* The summary is a flex row (h2 + chevron). Without this the heading
       cannot shrink below its min-content width and a long unbroken question
       would push the chevron out of the row at 375px. */
    min-width: 0;
}

/* --- "On this page" -------------------------------------------------------
   Jump list above the questions on every topic page with more than one. Plain
   anchors; the disclosure-opening in site.js is an enhancement over them, not
   a requirement (see Common/Topic.master). */
.on-this-page {
    max-width: var(--container-narrow);
    margin: 0 auto 36px;
    padding: 20px 24px;
    background: #fff;
    border: 1px solid var(--gray-200);
    border-radius: var(--radius);
}

    .on-this-page__title {
        margin: 0 0 10px;
        font-size: 1rem;
        font-weight: 700;
        letter-spacing: .02em;
        text-transform: uppercase;
        color: var(--gray-500);
    }

    .on-this-page__list {
        margin: 0;
        padding: 0 0 0 1.3em;
        list-style: decimal;
    }

    .on-this-page__list li {
        margin: 0 0 6px;
        font-size: 1.0625rem;
        line-height: 1.5;
    }

    .on-this-page__list li:last-child {
        margin-bottom: 0;
    }

    .on-this-page__list a {
        color: var(--brand-darker);
        text-decoration: none;
    }

        .on-this-page__list a:hover,
        .on-this-page__list a:focus-visible {
            text-decoration: underline;
        }

@media (max-width: 640px) {
    .on-this-page {
        padding: 16px 18px;
    }
}

/* --- Contact form ---------------------------------------------------------
   The one server form on the site (see README rule 1). Antiforgery and
   honeypot are handled in Pages/ContactUs.aspx. */
.form {
    max-width: 640px;
    margin: 0 auto;
    text-align: left;
}

.form__row {
    margin-bottom: 18px;
}

    .form__row label {
        display: block;
        margin-bottom: 6px;
        font-size: 1rem;
        font-weight: 600;
    }

.form__optional {
    font-weight: 400;
    color: var(--gray-500);
}

.form input[type="text"],
.form input[type="email"],
.form input[type="tel"],
.form textarea {
    width: 100%;
    padding: 12px 14px;
    font: inherit;
    font-size: 1.0625rem;
    color: var(--text);
    background: var(--white);
    border: 1px solid var(--gray-300);
    border-radius: var(--radius);
}

    /* Fires on pointer focus too, not just :focus-visible -- clicking into a
       field should show where you landed. Cyan at 2.53:1 on the white field
       was too faint to do that, so the ring takes --brand-darker (5.47:1);
       the border keeps the brand cyan as the colour cue it always was. */
    .form input:focus,
    .form textarea:focus {
        outline: 2px solid var(--brand-darker);
        outline-offset: 1px;
        border-color: var(--brand);
    }

.form textarea {
    min-height: 170px;
    resize: vertical;
}

.form .btn {
    margin-top: 6px;
}

/* Honeypot: parked off-screen rather than display:none, which some bots
   detect and skip. Humans never see or tab into it. */
.form__hp {
    position: absolute !important;
    left: -9999px !important;
    top: auto;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.form-alert {
    max-width: 640px;
    margin: 0 auto 24px;
    padding: 14px 18px;
    border-radius: var(--radius);
    font-size: 1.0625rem;
    text-align: left;
}

.form-alert--error {
    background: #fef3f2;
    border: 1px solid #f04438;
}

.form-alert--success {
    background: #ecfdf3;
    border: 1px solid var(--green);
    text-align: center;
}

    /* The summary and the success panel both take focus when the postback
       lands (tabindex="-1" + autofocus, see Pages/ContactUs.aspx). They are
       not in the tab order, so the ring is the only thing telling a sighted
       keyboard user where focus went — it has to show.

       :focus, not :focus-visible. If the sender submitted by clicking, Chrome
       decides the autofocus that follows is not a keyboard interaction and
       :focus-visible does not match, so the ring would never paint for the
       most common way of submitting the form. These panels are tabindex="-1"
       and take focus only when we put it there, so there is no stray-ring
       cost to matching plain :focus. */
    .form-alert:focus {
        outline: 3px solid var(--focus-ring);
        outline-offset: 2px;
        box-shadow: 0 0 0 2px var(--focus-ring-inner);
    }

/* The site-wide `ul` reset strips list-style; put it back here. A summary of
   three problems should look like three problems, not a run of sentences. */
.form-alert__list {
    margin: 8px 0 0;
    padding-left: 20px;
    list-style: disc;
}

    .form-alert__list li + li {
        margin-top: 4px;
    }

    /* Measured against the tint the panel actually is, not against white:
       #b42318 on #fef3f2 is 6.05:1. The panel's own border red (#d92d20)
       would have been 4.44:1 there and missed 4.5:1, which is why the text
       goes a step darker than the border does. */
    .form-alert__list a {
        color: #b42318;
        font-weight: 600;
    }

/* Per-field message, rendered under the input it belongs to and referenced
   from that input's aria-describedby. Same red as the summary links; on the
   white page background that is 6.57:1. */
.form__error {
    margin: 6px 0 0;
    font-size: .9375rem;
    font-weight: 600;
    color: #b42318;
}

.form [aria-invalid="true"] {
    border-color: #d92d20;
}

/* Contact page: intro copy on the left, the form on the right. Stacks on
   narrow screens with the copy first. */
.contact-split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(28px, 4vw, 60px);
    align-items: start;
}

    /* The intro keeps the section-head display treatment but sits in its
       column: left-aligned, no centering or bottom gap. */
    .contact-split .section-head {
        margin: 0;
        text-align: left;
    }

    .contact-split .form,
    .contact-split .form-alert {
        margin-left: 0;
        margin-right: 0;
    }

    /* The copy comes first in the DOM so it stacks on top when the columns
       collapse; on desktop the form is pulled to the left column instead. */
    .contact-split .contact-split__form {
        order: -1;
    }

/* The email alternative above the form: quiet, but sized to stay comfortably
   readable rather than fine print. */
.contact-split__alt {
    margin: 0 0 20px;
    font-size: .9375rem;
    line-height: 1.7;
    color: var(--gray-600);
}

@media (max-width: 860px) {
    .contact-split {
        grid-template-columns: 1fr;
    }

        .contact-split .contact-split__form {
            order: 0;
        }
}

/* --- Final CTA ----------------------------------------------------------- */
.cta {
    padding: clamp(48px, 7vw, 80px) 0;
    background: var(--white);
    color: var(--text);
    text-align: center;
}

    .cta h2 {
        color: var(--text);
        font-family: var(--font-display);
        font-size: calc(1.675rem + 5.1vw);
        line-height: 1.15;
        letter-spacing: 0;
        text-wrap: balance;
    }

    .cta p {
        max-width: 46em;
        margin-inline: auto;
        font-size: 1.25rem;
        color: var(--text);
    }

.cta__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 12px;
    margin-top: 28px;
}

/* The longer sign-up label will not sit on one line in a shrink-to-fit
   button at 320px. Same treatment the hero row already gets: full width in
   a capped centred column with trimmed side padding, so the label stays on
   one line. Above this width the button keeps its shrink-to-fit sizing. */
@media (max-width: 600px) {
    .cta__actions .btn--lg {
        width: 100%;
        max-width: 340px;
        padding-inline: 14px;
        font-size: 1rem;
    }
}
/* Arrow pointing back up at the sign-up button. */
.cta__arrow {
    display: block;
    margin: 18px auto 0;
    /* Matches the marker highlight and underline orange. */
    color: #fbb945;
}

.cta p.cta__note {
    /* Sits under the arrow, deliberately quiet — the one place on the
     page that stays muted rather than black. */
    margin-top: 10px;
    font-size: .875rem;
    line-height: 1.7;
    color: var(--gray-500);
}

/* Pricing under the closing CTA. Deliberately no font-size: it inherits
   .cta p, which is the page's body size (1.25rem, set on body), so the price
   reads as information someone is looking for rather than as the .cta__note
   fine print it used to sit inside. It stays secondary to the sign-up button
   by being plain centred text under a large filled button -- not by being
   shrunk, which is what made it look like a disclaimer before. */
.cta p.cta__price {
    margin-top: 18px;
    /* Slightly tighter than the body 1.6 so the two lines read as one block
       rather than as two separate sentences. */
    line-height: 1.5;
}

    /* A nudge, not a shout: <b> defaults to 700, which is heavy next to body
       text at this size. */
    .cta p.cta__price b {
        font-weight: 600;
    }

    /* Matches the "See all industries" action link (.usecase__more): same
       --brand-darker blue, weight 600, no underline until hover. Only the
       weight is declared here -- the blue already comes from the global a
       rule (the same variable .usecase__more names), the hover underline from
       a:hover, and keyboard focus from :focus-visible, so there is no bespoke
       hover or focus treatment to drift out of step.

       Not the .usecase__more class itself: that is a standalone action link
       carrying its own inline-flex box, gap, margin-top and .9375rem size,
       and this link sits inline inside a sentence at the block's body size.

       Colour is not the only cue, so dropping the resting underline does not
       leave the link on colour alone: 600 against the surrounding 400 body
       text distinguishes it without relying on hue. */
    .cta p.cta__price a {
        font-weight: 600;
    }

/* --- Footer -------------------------------------------------------------- */
.site-footer {
    /* Columns are the last thing in the footer now, so the bottom padding
       carries the whole gap to the page edge. */
    padding: clamp(32px, 3.5vw, 44px) 0 clamp(40px, 5vw, 56px);
    background: var(--navy);
    color: var(--gray-400);
    font-size: .9375rem;
}

    .site-footer a {
        color: var(--gray-300);
    }

        .site-footer a:hover {
            color: var(--white);
        }

.site-footer__top {
    display: grid;
    /* Single column by default; widen only when there is room. Using auto-fit
     with a fixed min on every column overflows narrow phones. */
    grid-template-columns: 1fr;
    gap: 36px;
}

@media (min-width: 560px) {
    .site-footer__top {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 900px) {
    /* Three link columns and the description. The description used to take
       half the footer on its own, against two link columns; a third link
       column was added Sep 2026, so it gives some of that width back —
       1+1+1+1.7 puts it at about 37% rather than 50%, which is enough for
       its own measure (capped at 60ch below) without squeezing the links.

       The link columns are 1fr rather than auto so all three keep the same
       width and their headings line up; sizing them to content would stagger
       them, since "New to InOutBoard?" is much wider than "About us". */
    .site-footer__top {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.7fr);
        gap: 40px;
    }
}

/* Brand block sits above the link columns, centred across the whole footer,
   rather than occupying the first grid column. */
.site-footer__brand {
    margin-bottom: clamp(24px, 2.5vw, 32px);
    text-align: center;
}

    /* Block, not inline, so the gap below the logo is exactly the margin
       above — no baseline leading padding it out. */
    .site-footer__brand img {
        display: block;
        width: 160px;
        height: auto;
        margin: 0 auto;
    }

/* Headerless third column: the blurb and the social links. Sits alongside
   the link columns, so it starts level with their headings. */
.site-footer__about p {
    /* Wide enough to fill the half-width column, still capped so the lines
       stay readable. */
    max-width: 60ch;
    font-size: .875rem;
}

.site-footer__about .social {
    margin-top: 20px;
}

.site-footer h2 {
    margin-bottom: 14px;
    font-size: 1rem;
    font-weight: 700;
    color: var(--white);
}

.site-footer__links li {
    margin-bottom: 10px;
}

.social {
    display: flex;
    gap: 10px;
}

    .social a {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 40px;
        height: 40px;
        border-radius: var(--radius-sm);
        background: rgba(255, 255, 255, .08);
        color: var(--gray-300);
        transition: background-color .15s ease, color .15s ease;
    }

        .social a:hover {
            background: var(--brand);
            color: var(--white);
        }

/* --- 404 and error pages -------------------------------------------------
   Shared by PageNotFound.aspx and Error.aspx.
   Layout lives here rather than in style attributes on PageNotFound.aspx.
   The site's CSP has no 'unsafe-inline' in style-src, so inline styles were
   blocked outright and the page rendered unstyled: full-width, left-aligned,
   with the shortcut links stacked instead of in a row. */
.notfound {
    /* Narrower than the standard container. Declared after .container so it
       wins on source order. Wide enough that the h1 stays on one line at its
       56px desktop size ("We couldn't find that page" measures ~692px); the
       lede below keeps the old, narrower measure so the copy stays readable. */
    max-width: 760px;
    text-align: center;
}

/* On a phone the heading still has to wrap; balance keeps the two lines even
   instead of leaving one word on its own. */
.notfound h1 {
    text-wrap: balance;
}

/* Scout: under the heading on the 404 page, above it on Error.aspx. The
   bottom margin works for both, since h1 brings its own. The art is a transparent cut-out, so it sits on
   any section background without a white box around it. */
.notfound__scout {
    display: block;
    width: 200px;
    height: auto;
    margin: 0 auto 24px;
}

.notfound__lede {
    max-width: 592px;
    margin-inline: auto;
    font-size: 1.125rem;
    color: var(--gray-500);
}

/* Secondary shortcuts under the two buttons. */
.notfound__links {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 12px 28px;
    margin-top: 36px;
}
