/* ==========================================================================
   Vestfold — landing UI layer
   Components and interaction states added on top of landing.html's base.
   Everything here is additive: with no JS, no GSAP or reduced motion, every
   block below renders finished and static. Motion is gated on html.js, which
   landing.html only sets once GSAP is confirmed live.
   ========================================================================== */

/* ---------- shared: masked line reveal ---------- */
/* A heading is split into .rvl-line wrappers at runtime; each holds an inner
   .rvl-inner that slides up from under its own clip. No JS = no wrappers =
   plain text, which is why the base heading rules are untouched. */
.rvl-line {
    display: block;
    overflow: hidden;
    padding-bottom: 0.06em;
    margin-bottom: -0.06em;
}

.rvl-inner {
    display: block;
}

/* ---------- scroll progress ---------- */
.vf-progress {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    z-index: 60;
    background: var(--red);
    transform: scaleX(0);
    transform-origin: 0 50%;
    pointer-events: none;
}

/* ---------- magnetic buttons ---------- */
/* The transform is written by JS; the transition here only covers the
   release, so the pull feels instant and the return feels sprung. */
[data-magnet] {
    position: relative;
}

.btn {
    position: relative; /* contain animated overlay inside button */
    overflow: hidden;
    isolation: isolate;
}

/* Fill wipes up from the bottom edge rather than cross-fading, which is what
   stops the buttons reading like a bootstrap default. */
.btn::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: var(--ink);
    transform: translateY(101%);
    transition: transform .42s cubic-bezier(.22, 1, .36, 1);
}

.btn--solid::after {
    background: var(--red);
}

.btn--outline::after,
.btn--ghost::after {
    background: var(--ink);
}

.btn--light::after {
    background: var(--cream);
}

.btn:hover::after,
.btn:focus-visible::after {
    transform: translateY(0);
}

.btn--outline:hover,
.btn--ghost:hover {
    color: var(--cream);
}

.btn--light:hover {
    color: var(--ink);
}

/* ---------- logo wall ---------- */
.logos {
    position: relative;
    z-index: 1;
    border-top: 2px solid var(--ink);
    border-bottom: 2px solid var(--ink);
    background: var(--cream);
    padding: 22px 0;
    overflow: hidden;
}

.logos__head {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 14px;
    margin-bottom: 18px;
    padding: 0 var(--gutter);
}

.logos__label {
    display: block;
    text-align: center;
    font-size: 11px;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--label);
}

/* Focusable marquee viewport is the pause control, with no separate button. */
.logos__viewport:focus-visible { outline: 3px solid var(--red); outline-offset: -4px; }

.logos__viewport {
    position: relative;
    overflow: hidden;
}

/* Feathered ends so logos enter and leave rather than pop at the edge. Only
   while the marquee is actually running: on the static page the first logo
   would just look half-erased. */
.js .logos__viewport {
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}

.logos__track {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    row-gap: 18px;
    column-gap: clamp(38px, 6vw, 86px);
    padding: 0 var(--gutter);
    will-change: transform;
}

/* Running, the row must be one unbroken line wider than the viewport. At
   rest it wraps and centres instead, so the static page shows every client
   rather than clipping the last two. */
.js .logos__track {
    flex-wrap: nowrap;
    justify-content: flex-start;
    width: max-content;
    padding: 0;
}

/* Without JS the track sits still and shows the first run of logos, which is
   a complete, legible strip — the duplicate run is only there for the loop. */
.logos__run {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    row-gap: 18px;
    column-gap: clamp(38px, 6vw, 86px);
}

/* The run is a single flex child, so wrapping has to happen on the run
   itself — wrapping the track around it would do nothing. */
.js .logos__run {
    flex-wrap: nowrap;
    justify-content: flex-start;
    flex: none;
}

.logos__run[aria-hidden="true"] {
    display: none;
}

.js .logos__run[aria-hidden="true"] {
    display: flex;
}

.logo-chip {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: none;
    filter: grayscale(1);
    opacity: .52;
    transition: opacity .3s ease, filter .3s ease, transform .3s cubic-bezier(.22, 1, .36, 1);
}

.logo-chip:hover {
    opacity: 1;
    filter: grayscale(0);
    transform: translateY(-3px);
}

.logo-chip img {
    height: 34px;
    width: auto;
    /* Wordmarks are far wider than seals; without a cap one client eats the
       whole run and the marquee loses its rhythm. */
    max-width: 92px;
    object-fit: contain;
}

.logo-chip__name {
    font-family: 'GTAX', 'GTA', sans-serif;
    font-size: 15px;
    font-weight: 700;
    letter-spacing: .01em;
    white-space: nowrap;
    color: var(--ink);
}

.logo-chip__meta {
    display: block;
    font-family: 'GTA', sans-serif;
    font-size: 10.5px;
    font-weight: 400;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--label);
    margin-top: 3px;
}

/* A monogram stands in where a client has no mark we own the rights to use.
   Same box as a real logo, so the row never looks half-built. */
.logo-chip__mono {
    width: 34px;
    height: 34px;
    display: grid;
    place-items: center;
    flex: none;
    box-shadow: inset 0 0 0 1.5px var(--ink);
    font-family: 'GTAX', 'GTA', sans-serif;
    font-size: 12px;
    font-weight: 900;
    letter-spacing: .02em;
}

/* ==========================================================================
   The screen — scattered sources become one dashboard
   The centrepiece. It is the only place on the page where the product is
   shown rather than described, so it gets the pin and the scrub.
   ========================================================================== */
.screen {
    position: relative;
    z-index: 1;
    padding: clamp(30px, 4vw, 56px) var(--gutter);
}

.screen__panel {
    max-width: 1240px;
    margin: 0 auto;
    background: var(--cream);
    box-shadow: inset 0 0 0 2px var(--ink);
    padding: clamp(28px, 4vw, 48px);
}

.screen__stage {
    display: grid;
    grid-template-columns: minmax(190px, 240px) minmax(90px, 150px) 1fr;
    align-items: center;
    gap: 0;
    margin-top: clamp(24px, 3vw, 38px);
}

/* ---------- left: the systems a business already runs on ---------- */
.sources {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.source {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    background: var(--cream);
    box-shadow: inset 0 0 0 1.5px var(--ink);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: .01em;
}

.source__dot {
    width: 7px;
    height: 7px;
    flex: none;
    border-radius: 50%;
    background: var(--stone);
}

.source__tag {
    margin-left: auto;
    font-size: 10.5px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--label);
    white-space: nowrap;
}

/* Before the wires land, each source is its own island: that is the problem
   the section is about, so it is drawn rather than stated. */
.source.is-stranded .source__dot {
    background: var(--red);
}

.source.is-joined .source__dot {
    background: var(--green);
}

/* ---------- middle: the wiring ---------- */
.wires {
    width: 100%;
    height: 100%;
    min-height: 240px;
    overflow: visible;
}

.wire {
    fill: none;
    stroke: var(--ink);
    stroke-width: 1.5;
    stroke-linecap: round;
}

.wire-node {
    fill: var(--cream);
    stroke: var(--ink);
    stroke-width: 2;
}

.wire-pulse {
    fill: var(--red);
}

/* ---------- right: the dashboard itself ---------- */
.dash {
    background: var(--cream);
    box-shadow: inset 0 0 0 2px var(--ink);
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.dash__bar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    border-bottom: 1.5px solid var(--ink);
}

.dash__dots {
    display: flex;
    gap: 5px;
}

.dash__dots i {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--stone);
    display: block;
}

.dash__title {
    font-size: 11px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--label);
}

.dash__live {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 10.5px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--green);
}

.dash__live i {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--green);
    display: block;
}

.dash__kpis {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    border-bottom: 1.5px solid var(--ink);
}

.kpi {
    display: flex;
    flex-direction: column;
    padding: 14px 16px;
    border-right: 1.5px solid var(--ink);
    min-width: 0;
}

.kpi:last-child {
    border-right: 0;
}

/* Labels wrap rather than truncate; the values below them share a baseline
   because the value is pushed to the bottom of the cell. */
.kpi__label {
    display: block;
    font-size: 10.5px;
    line-height: 1.3;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--label);
}

.kpi__value {
    display: block;
    font-family: 'GTAX', 'GTA', sans-serif;
    font-size: clamp(19px, 2.1vw, 27px);
    font-weight: 900;
    line-height: 1.05;
    margin-top: auto;
    padding-top: 6px;
    font-variant-numeric: tabular-nums;
}

.kpi__delta {
    display: inline-block;
    margin-top: 5px;
    font-size: 10.5px;
    letter-spacing: .04em;
    color: var(--green);
}

.kpi--red .kpi__value {
    color: var(--red);
}

.kpi--navy .kpi__value {
    color: var(--navy);
}

.kpi--green .kpi__value {
    color: var(--green);
}

.dash__chart {
    padding: 16px;
    border-bottom: 1.5px solid var(--ink);
}

.chart {
    width: 100%;
    height: auto;
    display: block;
    overflow: visible;
}

.chart__grid {
    stroke: var(--stone);
    stroke-width: .6;
    opacity: .6;
}

.chart__area {
    fill: var(--blush);
    opacity: .75;
}

.chart__line {
    fill: none;
    stroke: var(--red);
    stroke-width: 2.2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.chart__base {
    fill: none;
    stroke: var(--stone);
    stroke-width: 1.6;
    stroke-dasharray: 4 4;
}

.chart__bar {
    fill: var(--ink);
}

.chart__head {
    fill: var(--red);
    stroke: var(--cream);
    stroke-width: 2;
}

.dash__rows {
    padding: 4px 0 6px;
}

.drow {
    display: grid;
    grid-template-columns: 1fr auto auto;
    gap: 12px;
    align-items: center;
    padding: 7px 16px;
    font-size: 11.5px;
    border-bottom: 1px solid rgba(185, 178, 166, .5);
}

.drow:last-child {
    border-bottom: 0;
}

.drow__name {
    color: var(--body);
    min-width: 0;
}

.drow__val {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
}

.drow__pill {
    font-size: 10.5px;
    letter-spacing: .07em;
    text-transform: uppercase;
    padding: 2px 7px;
    box-shadow: inset 0 0 0 1px currentColor;
    color: var(--green);
    white-space: nowrap;
}

.drow__pill.is-warn {
    color: var(--red);
}

.screen__caption {
    margin: clamp(20px, 2.6vw, 30px) 0 0;
    font-size: 13px;
    line-height: 1.6;
    color: var(--muted);
    max-width: 62ch;
}

/* Below the three-column stage the wiring stops meaning anything, so the
   sources sit as a row of chips above the dashboard instead. */
@media (max-width: 900px) {
    .screen__stage {
        grid-template-columns: 1fr;
        gap: 18px;
    }

    .wires {
        display: none;
    }

    .sources {
        flex-direction: row;
        flex-wrap: wrap;
    }

    .source {
        flex: 1 1 auto;
        font-size: 11px;
        padding: 7px 10px;
    }

    .source__tag {
        display: none;
    }

    .dash__kpis {
        grid-template-columns: repeat(3, 1fr);
    }

    .kpi {
        padding: 11px 10px;
    }
}

/* ==========================================================================
   Service cards — lift, spotlight, and a diagram that runs on hover
   ========================================================================== */
.card {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    transition: transform .5s cubic-bezier(.22, 1, .36, 1), box-shadow .5s cubic-bezier(.22, 1, .36, 1);
}

/* --mx/--my are written by pointermove; the fallback keeps the highlight
   parked in the middle for keyboard focus and for pointers that never move. */
.card::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    opacity: 0;
    transition: opacity .4s ease;
    background: radial-gradient(420px circle at var(--mx, 50%) var(--my, 50%),
            rgba(155, 29, 32, .09), transparent 62%);
}

.card:hover::before,
.card:focus-within::before {
    opacity: 1;
}

.card:hover,
.card:focus-within {
    box-shadow: inset 0 0 0 2px var(--ink), 0 18px 34px -24px rgba(11, 11, 11, .55);
}

/* A rule that grows out from under the eyebrow — the smallest possible
   signal that the card is live, and it costs no layout. */
.card__rule {
    display: block;
    height: 2px;
    width: 26px;
    background: var(--red);
    margin: 10px 0 2px;
    transform-origin: 0 50%;
    transition: transform .5s cubic-bezier(.22, 1, .36, 1);
}

.card:hover .card__rule,
.card:focus-within .card__rule {
    transform: scaleX(3.2);
}

.card__viz {
    display: block;
    width: 100%;
    max-width: 190px;
    height: auto;
    margin: 14px 0 2px;
    overflow: visible;
}

.viz-stroke {
    fill: none;
    stroke: var(--ink);
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.viz-accent {
    fill: var(--red);
}

.viz-bar {
    fill: var(--ink);
    transform-box: fill-box;
    transform-origin: 50% 100%;
}

.viz-dot {
    fill: var(--cream);
    stroke: var(--ink);
    stroke-width: 1.6;
}

.viz-ghost {
    fill: none;
    stroke: var(--stone);
    stroke-width: 1.4;
    stroke-dasharray: 3 3;
}

/* ==========================================================================
   Case cards — logo colour on hover, sparkline that draws
   ========================================================================== */
.case {
    position: relative;
    transition: transform .5s cubic-bezier(.22, 1, .36, 1), box-shadow .5s cubic-bezier(.22, 1, .36, 1);
}

.case:hover {
    /* Keep hover from fighting GSAP's reveal transform. */
    box-shadow: 0 15px 30px -25px rgba(11, 11, 11, .65);
}

.case__logo {
    filter: grayscale(1);
    opacity: .75;
    transition: filter .35s ease, opacity .35s ease;
}

.case:hover .case__logo {
    filter: grayscale(0);
    opacity: 1;
}

.case__spark {
    display: block;
    width: 100%;
    height: auto;
    margin-top: auto;
    padding-top: 14px;
    overflow: visible;
}

.spark-line {
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.spark-line.is-red {
    stroke: var(--red);
}

.spark-line.is-navy {
    stroke: var(--navy);
}

.spark-line.is-green {
    stroke: var(--green);
}

.spark-base {
    stroke: var(--stone);
    stroke-width: 1.2;
    stroke-dasharray: 3 3;
    fill: none;
}

.spark-axis {
    fill: var(--label);
    font-size: 8px;
    letter-spacing: .08em;
    text-transform: uppercase;
}

/* ==========================================================================
   Process — a rail that moves sideways while the section is pinned
   ========================================================================== */
.rail {
    position: relative;
    overflow: hidden;
}

/* No display here on purpose. The track is also a .framed__grid--process,
   and that grid is what the four steps use everywhere the rail is not
   pinned. Setting flex at this level made it a nowrap row at every width,
   so on a phone steps three and four sat outside a 256px rail with
   overflow: hidden over them and no way to reach them. The flex row
   belongs to the pinned rail alone, and is set with it below. */
.rail__track {
    gap: 0;
}

/* Only meaningful while the rail is pinned and travelling; the script marks
   the rail when it has actually built that. */
.rail__progress {
    display: none;
    position: relative;
    height: 2px;
    background: var(--stone);
    margin-top: 20px;
}

.js .rail--pinned+.rail__progress {
    display: block;
}

.rail__progress i {
    position: absolute;
    inset: 0;
    display: block;
    background: var(--ink);
    transform: scaleX(0);
    transform-origin: 0 50%;
}

/* Without JS the four steps stay a plain grid: the rail only engages when
   the pin does, which is why the flex row is scoped to .js and wide screens. */
@media (min-width: 901px) {
    .js .rail__track .step {
        flex: 0 0 min(430px, 40vw);
    }
}

.step {
    position: relative;
    transition: background-color .4s ease;
}

.step__num {
    display: block;
    font-family: 'GTAX', 'GTA', sans-serif;
    font-size: clamp(34px, 4.4vw, 58px);
    font-weight: 900;
    line-height: .9;
    color: transparent;
    -webkit-text-stroke: 1.5px var(--stone);
    margin-bottom: 10px;
    transition: -webkit-text-stroke-color .45s ease, color .45s ease;
}

.step:hover .step__num,
.step.is-active .step__num {
    -webkit-text-stroke-color: var(--red);
}

/* ==========================================================================
   Testimonials — pull-quote treatment
   ========================================================================== */
.quote {
    position: relative;
    transition: transform .5s cubic-bezier(.22, 1, .36, 1), box-shadow .5s cubic-bezier(.22, 1, .36, 1);
}

.quote:hover {
    transform: translateY(-4px);
    box-shadow: 0 20px 38px -26px rgba(11, 11, 11, .6);
}

.quote__mark {
    display: block;
    font-family: 'GTAX', 'GTA', sans-serif;
    font-size: 64px;
    font-weight: 900;
    line-height: .7;
    color: var(--blush);
    margin-bottom: 4px;
    user-select: none;
}

.quote__avatar {
    width: 38px;
    height: 38px;
    flex: none;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--ink);
    color: var(--cream);
    font-family: 'GTAX', 'GTA', sans-serif;
    font-size: 13px;
    font-weight: 900;
    letter-spacing: .02em;
}

.quote__by {
    display: flex;
    align-items: center;
    gap: 12px;
}

/* ==========================================================================
   FAQ — real accordion
   ========================================================================== */
/* <details> is the whole mechanism: open/closed works with no JS at all.
   GSAP only smooths the height and spins the sign. */
.faq-item {
    padding: 0 !important;
}

.faq-item summary {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    cursor: pointer;
    list-style: none;
    padding: clamp(16px, 2vw, 22px);
    transition: background-color .3s ease;
}

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

.faq-item summary:hover {
    background: rgba(232, 214, 203, .45);
}

.faq-item summary h3 {
    margin: 0;
    flex: 1;
}

.faq-item__sign {
    position: relative;
    width: 15px;
    height: 15px;
    flex: none;
    margin-top: 3px;
}

.faq-item__sign::before,
.faq-item__sign::after {
    content: "";
    position: absolute;
    background: var(--ink);
    transition: transform .35s cubic-bezier(.22, 1, .36, 1), opacity .35s ease;
}

.faq-item__sign::before {
    top: 7px;
    left: 0;
    width: 15px;
    height: 1.5px;
}

.faq-item__sign::after {
    left: 6.75px;
    top: 0;
    width: 1.5px;
    height: 15px;
}

.faq-item[open] .faq-item__sign::after {
    transform: rotate(90deg);
    opacity: 0;
}

.faq-item__body {
    overflow: hidden;
}

.faq-item__body p {
    margin: 0;
    padding: 0 clamp(16px, 2vw, 22px) clamp(16px, 2vw, 22px);
}

/* ==========================================================================
   Contact — grain over the reversed panel
   ========================================================================== */
.panel--contact {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

.panel--contact::before {
    content: "";
    position: absolute;
    inset: -50%;
    z-index: -1;
    opacity: .16;
    background-image: radial-gradient(rgba(239, 235, 226, .8) .5px, transparent .5px);
    background-size: 4px 4px;
}

.contact__title span {
    display: inline-block;
}

@media (prefers-reduced-motion: reduce) {

    .card,
    .case,
    .quote,
    .btn::after,
    .card__rule,
    .logo-chip {
        transition: none !important;
    }

    .panel--contact::before {
        animation: none !important;
    }
}

/* Bars grow from their own baseline rather than the SVG's. */
.chart__bar,
.viz-bar {
    transform-box: fill-box;
    transform-origin: 50% 100%;
}

.chart__bar {
    fill: var(--stone);
    opacity: .38;
}

/* The screen's own head block reuses the section head rhythm. */
.screen__title {
    font-family: 'GTAX', 'GTA', sans-serif;
    font-size: var(--heading);
    font-weight: 900;
    line-height: 1.04;
    letter-spacing: -0.01em;
    margin: 6px 0 0;
    text-transform: uppercase;
}

/* The rail only becomes a flex run when it is actually going to be pinned;
   otherwise it stays the auto-fit grid the markup already had. */
@media (min-width: 901px) {
    .js .rail__track {
        display: flex;
        flex-wrap: nowrap;
    }
}

/* ==========================================================================
   Touch and small screens
   Two separate concerns, deliberately kept apart:
     - (pointer: coarse) sizes hit areas for a finger, at any width;
     - width queries reflow the layouts that stop working when they narrow.
   ========================================================================== */

/* ---------- hit areas ---------- */
/* WCAG 2.5.8 asks for 24px; a thumb wants 44. Padding grows the target
   without moving the text, so each block keeps the rhythm it was drawn with. */
@media (pointer: coarse) {

    /* Padding only, never a negative margin: pulling the box back in would
       make the hit areas of two wrapped rows overlap, and a tap landing
       between them would open the wrong page. The rows are spaced to clear
       each other instead, which costs a little height at the foot of the
       page and nothing anywhere else. */
    .site-footer__links a {
        padding: 15px 0;
    }

    .site-footer__links {
        gap: 2px 24px;
    }

    .crumbs a {
        padding: 9px 0;
    }

    .crumbs {
        gap: 6px 8px;
    }

    .site-footer__brand a {
        display: inline-block;
        padding: 10px 0;
        margin: -10px 0;
    }

    /* The toggle is the only control in the header, so it gets a full 44. */
    .nav__toggle {
        width: 46px;
        height: 44px;
    }

    .nav__toggle i {
        left: 14px;
    }

    .nav__toggle i:nth-child(1) {
        top: 18px;
    }

    .nav__toggle i:nth-child(2) {
        top: 26px;
    }

    .brand {
        padding: 9px 0;
        margin: -9px 0;
    }

    /* There is no hover on a touch screen, so a client's mark would stay
       greyed out for good. Show them the way a desktop visitor sees them. */
    .case__logo {
        filter: none;
        opacity: 1;
    }

    .logo-chip {
        opacity: .78;
    }

    /* Nothing here reacts to a pointer that cannot hover, and a stuck
       :hover after a tap is worse than no effect at all. */
    .card:hover,
    .case:hover,
    .quote:hover,
    .tier:hover,
    .next-card:hover,
    .logo-chip:hover {
        transform: none;
    }
}

/* A long guide's contents list becomes the first thing on the page when the
   sidebar collapses. Ruled rows read as a list and carry a 44px target. */
@media (max-width: 980px) {
    .toc ol {
        border-top: 1px solid var(--stone);
    }

    .toc li {
        border-bottom: 1px solid var(--stone);
    }

    .toc li+li {
        margin-top: 0;
    }

    .toc a {
        padding: 14px 0;
    }

    .toc a:hover,
    .toc a.is-current {
        transform: none;
    }
}

/* ---------- the dashboard, below three columns ---------- */
/* Three KPI cells need about 110px each before the labels start stacking
   into towers. Under that they become rows: label, value, note. */
@media (max-width: 560px) {
    .dash__kpis {
        grid-template-columns: 1fr;
    }

    .kpi {
        flex-direction: row;
        align-items: baseline;
        gap: 10px;
        padding: 10px 14px;
        border-right: 0;
        border-bottom: 1px solid rgba(185, 178, 166, .5);
    }

    .kpi:last-child {
        border-bottom: 0;
    }

    .kpi__label {
        flex: 1;
        min-width: 0;
    }

    .kpi__value {
        margin-top: 0;
        padding-top: 0;
        font-size: 21px;
    }

    .kpi__delta {
        margin-top: 0;
        flex: none;
    }
}

/* The report rows run out of room for three columns before the KPIs do:
   the name gets a line of its own and the status sits under it. */
@media (max-width: 480px) {
    .drow {
        grid-template-columns: 1fr auto;
        gap: 3px 10px;
        padding: 9px 14px;
    }

    .drow__name {
        grid-column: 1 / -1;
    }
}

/* ---------- the narrowest phones ---------- */
/* A 320px screen loses 96px to the gutter and the panel inset before a word
   is set. Tightening both gives the measure back about a dozen characters. */
@media (max-width: 400px) {
    :root {
        --gutter: 15px;
        --heading: 25px;
    }

    .panel,
    .screen__panel {
        padding: 22px 17px;
    }

    .page-hero__panel,
    .article__panel {
        padding: 22px 17px;
    }

    .panel--contact {
        padding: 38px 20px;
    }

    .card,
    .quote {
        padding: 22px 18px;
    }

    .case__body,
    .case__head {
        padding-left: 18px;
        padding-right: 18px;
    }

    .faq-item summary,
    .faq-item__body p {
        padding-left: 16px;
        padding-right: 16px;
    }

    .step {
        padding: 22px 18px 26px;
    }

    /* The expanded face is wide enough that one long word decides the size.
       At 320px "INTELLIGENCE?" needs 24px or less to stay on one line, and
       a heading that drops its last character onto a line of its own looks
       like a mistake rather than a break. */
    .page-hero__title {
        font-size: clamp(22px, 7vw, 26px);
    }

    .case__result {
        font-size: 27px;
    }

    .quote p {
        font-size: 16.5px;
        line-height: 26px;
    }

    .quote__mark {
        font-size: 48px;
    }

    .hero__lede,
    .contact__lede {
        font-size: 16.5px;
    }

    .term {
        padding-left: 16px;
        padding-right: 16px;
    }
}


/* The homepage owns its own logo strip layout and mobile marquee. */
