/* ============================================================================
   connecto.co.in -- public landing page.

   This file is deliberately NOT a second dark theme that happens to look
   nearby. Every token below is copied value-for-value from the application's
   own sign-in screen (Connecto/login.aspx) and chrome (assets/appnav.css),
   because the landing page and the console are two consecutive screens for the
   same visitor: read the page, press "Open the console", sign in. If the
   backdrop, the typeface, the card surface and the button gradient change
   under them at that hand-off, they are looking at two products.

   What was here before was orange (#ffad33 -> #ff6b6b) on a blue-grey
   gradient, with Segoe UI and 14px radii. Nothing in the application is
   orange. That palette is the main thing this rewrite removes.

   The one thing NOT copied from login.aspx is its root font-size:

       font-size: clamp(10.5px, 1.204vmin, 26px)

   That exists because sign-in runs full-screen on portrait kiosk panels of
   unknown size, so the whole card has to ride the short viewport edge. A
   public page is read on a phone held in portrait, where `vmin` is the width:
   the same rule would render this page at about 4px. Ordinary 16px root here,
   with clamp() on the display sizes only.
   ========================================================================= */

/* ============================== THEME ==============================
   Identical names and values to login.aspx :root, so a rule can be moved
   between the two files without translation. Radii are the application's
   1.15rem / 0.85rem, expressed against a 16px root rather than a scaled one,
   which lands them at 18.4px / 13.6px -- close to the chrome's own 20px
   panels and 14px controls. */
:root {
    --bg0: #060a13;
    --bg1: #0a1120;
    --card: rgba(15, 23, 42, 0.72);
    --line: rgba(140, 170, 255, 0.12);
    --line-hi: rgba(140, 170, 255, 0.26);
    --txt: #e9effd;
    --sub: #8ea3c7;
    --faint: #5b6f93;
    --acc: #00eac2;
    --acc2: #6fcaf8;
    --ok: #34e39d;
    --warn: #ffb454;
    --bad: #ff5c7a;
    --chip: rgba(111, 202, 248, 0.10);
    --hover: rgba(111, 202, 248, 0.08);
    --sheen: rgba(255, 255, 255, 0.06);
    --shadow: 0 1.4rem 3.1rem -1.4rem rgba(0, 0, 0, 0.65);
    --shadow-lg: 0 2.2rem 4.6rem -1.6rem rgba(0, 0, 0, 0.78);
    --r-lg: 1.45rem;
    --r-md: 1.15rem;
    --r-sm: 0.85rem;
    --r-xs: 0.55rem;

    /* One measurement, used by the page gutter, the top bar and every
       section, so the bar's wordmark sits on the same vertical line as the
       hero heading and the footer's first column. The application makes the
       same promise with --cnx-inset; this is that idea for a centred page. */
    --wrap: 1180px;
    --gut: 24px;

    /* Height the fixed bar occupies, including its top inset. Anchors offset
       themselves by this so a jump-to link never parks a heading underneath
       the bar. */
    --bar: 92px;
}

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

html {
    background: var(--bg0);
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
    scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
}

html, body {
    margin: 0;
    padding: 0;
    min-height: 100%;
}

body {
    font-family: 'Inter', 'Segoe UI', sans-serif;
    font-size: 16px;
    line-height: 1.6;
    color: var(--txt);
    /* The old page set `overflow: hidden` on body to force everything into one
       viewport. It is the reason the previous copy had to stay this short --
       anything more simply could not be reached. */
    overflow-x: hidden;
}

/* The application's backdrop, unchanged: three drifting radial washes over a
   165deg base. This is the strongest single signal that the page and the
   console belong together -- it is still drifting behind the sign-in card a
   moment later, uninterrupted by the navigation. */
body::before {
    content: "";
    position: fixed;
    inset: -12%;
    pointer-events: none;
    z-index: -1;
    background:
        radial-gradient(46vw 46vw at 78% 6%, rgba(0, 234, 194, 0.16), transparent 62%),
        radial-gradient(52vw 52vw at 10% 96%, rgba(111, 202, 248, 0.15), transparent 62%),
        radial-gradient(38vw 38vw at 52% 46%, rgba(126, 122, 255, 0.10), transparent 66%),
        linear-gradient(165deg, var(--bg0), var(--bg1));
    filter: blur(12px);
    animation: drift 34s ease-in-out infinite alternate;
}

@keyframes drift {
    from { transform: translate3d(0, 0, 0) scale(1); }
    to { transform: translate3d(-2.5%, 2%, 0) scale(1.06); }
}

/* Under Web Forms the whole page is inside one server <form>. Same fix the
   application uses in appnav.css: make it transparent to layout, or every
   section becomes a child of an element the stylesheet knows nothing about. */
body > form { display: contents; }

::selection { background: rgba(0, 234, 194, 0.28); color: #fff; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: rgba(140, 170, 255, 0.18); border-radius: 8px; }
::-webkit-scrollbar-thumb:hover { background: rgba(140, 170, 255, 0.3); }
::-webkit-scrollbar-track { background: transparent; }

img { max-width: 100%; height: auto; }

a { color: inherit; text-decoration: none; }

/* Every icon on the page is one <use> of the inline sprite at the top of the
   body, and the stroke geometry is set HERE rather than on each <symbol>.
   A <use> builds a shadow tree that inherits presentation from the use site,
   not from the symbol's original parent -- so fill/stroke attributes written
   once on the sprite's root <svg> look correct in the markup and apply to
   nothing at all. One rule on the consuming element is the version that
   works, and it costs 19 attributes per icon less. */
svg.i {
    fill: none;
    stroke: currentColor;
    stroke-width: 1.75;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* One visible focus treatment for every interactive element, drawn in the
   application's focus colour (login.aspx .inp:focus). Keyboard users get the
   same ring on a nav link that they get on a sign-in field. */
a:focus-visible,
button:focus-visible,
.btn:focus-visible {
    outline: 2px solid var(--acc);
    outline-offset: 3px;
    border-radius: var(--r-xs);
}

/* ============================== LAYOUT ============================== */
.wrap {
    width: 100%;
    max-width: var(--wrap);
    margin: 0 auto;
    padding: 0 var(--gut);
}

section { position: relative; }

/* Anchor targets clear the fixed bar. Without this, "Security" scrolls the
   heading to y=0 -- directly behind the bar -- and the section reads as
   starting at its second paragraph. */
[id] { scroll-margin-top: var(--bar); }

.sec { padding: clamp(64px, 8vw, 108px) 0; }

.sec-head { max-width: 46rem; margin-bottom: clamp(32px, 4vw, 52px); }

.sec-head.mid { margin-left: auto; margin-right: auto; text-align: center; }

/* The eyebrow + rule + heading trio is the application's brand block
   (login.aspx .brand-name / .brand-rule) turned into a section header, so
   every section opens with a mark the visitor has already seen. */
.eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    margin: 0 0 0.85rem;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--acc2);
}

.eyebrow::before {
    content: "";
    width: 1.6rem;
    height: 2px;
    border-radius: 2px;
    background: linear-gradient(90deg, var(--acc), var(--acc2));
}

/* The little gradient rule is a left-edge marker. Centred, it just hangs off
   one side of the label, so it goes wherever the eyebrow is centred. */
.sec-head.mid .eyebrow::before,
.cta .eyebrow::before { display: none; }

h1, h2, h3, h4 { margin: 0; font-weight: 700; letter-spacing: -0.02em; line-height: 1.15; }

/* `balance` on headings and `pretty` on body copy. Both are progressive: an
   engine without them wraps the way it always did, so neither is load-bearing
   -- they just stop a two-word third line hanging under a heading. */
h2 { font-size: clamp(1.65rem, 3.4vw, 2.4rem); text-wrap: balance; }

h3 { font-size: 1.06rem; letter-spacing: -0.01em; }

p { margin: 0; }

.lead {
    margin-top: 0.95rem;
    font-size: clamp(1rem, 1.5vw, 1.12rem);
    line-height: 1.72;
    color: var(--sub);
    text-wrap: pretty;
}

.muted { color: var(--faint); }

/* Skip link -- the page opens with a bar of nav links, and a keyboard visitor
   should not have to walk all of them to reach the article. */
.skip {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 200;
    padding: 0.7rem 1.1rem;
    border-radius: var(--r-sm);
    background: var(--acc);
    color: #04211c;
    font-weight: 700;
}

.skip:focus { left: var(--gut); top: 0.75rem; }

/* ============================== SURFACES ==============================
   `.card` is the application's card, matched property for property:
   translucent slate, one hairline in the chrome's blue-grey, an inset sheen
   along the top edge and an 18px backdrop blur. Everything panel-shaped on
   this page is built from it. */
.card {
    position: relative;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--card);
    box-shadow: var(--shadow), inset 0 1px 0 var(--sheen);
    -webkit-backdrop-filter: blur(18px) saturate(1.25);
    backdrop-filter: blur(18px) saturate(1.25);
}

/* ============================== BUTTONS ==============================
   .btn-go is login.aspx's `.go`: the acc -> acc2 sweep with near-black
   ink. It is the only element on the page allowed to use that gradient as a
   fill, which is what makes "Open the console" read as THE action. */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    height: 3.1rem;
    padding: 0 1.55rem;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    font-family: inherit;
    font-size: 1rem;
    font-weight: 700;
    white-space: nowrap;
    cursor: pointer;
    transition: filter 0.18s, transform 0.12s, background 0.18s, border-color 0.18s, color 0.18s;
}

.btn > svg { width: 1.05em; height: 1.05em; flex: none; }

.btn-go {
    background: linear-gradient(90deg, var(--acc), var(--acc2));
    color: #04211c;
    box-shadow: 0 0.9rem 2rem -0.9rem rgba(0, 234, 194, 0.55);
}

.btn-go:hover { filter: brightness(1.08); }
.btn-go:active { transform: translateY(1px); }

.btn-ghost {
    border-color: var(--line-hi);
    background: rgba(8, 14, 26, 0.5);
    color: var(--txt);
}

.btn-ghost:hover {
    border-color: rgba(0, 234, 194, 0.5);
    background: var(--hover);
    color: var(--acc);
}

.btn-sm { height: 2.5rem; padding: 0 1.05rem; font-size: 0.88rem; }

/* ============================== TOP BAR ==============================
   A floating rounded bar inset from the top, not a full-bleed strip: the
   application's chrome floats the same way (appnav.css insets the rail and
   top bar by --cnx-pad and rounds them to 20px), and copying that shape is
   what makes the page feel like the console's front door. */
.bar {
    position: fixed;
    top: 14px;
    left: 0;
    right: 0;
    z-index: 100;
    padding: 0 var(--gut);
}

.bar-in {
    display: flex;
    align-items: center;
    gap: 1.1rem;
    max-width: var(--wrap);
    height: 64px;
    margin: 0 auto;
    padding: 0 0.85rem 0 1.1rem;
    border: 1px solid transparent;
    border-radius: 18px;
    transition: background 0.25s, border-color 0.25s, box-shadow 0.25s, backdrop-filter 0.25s;
}

/* Transparent over the hero, solid once the page has moved. Toggled from
   landing.js rather than guessed at with a scroll-linked gradient, so the
   bar is either fully legible or fully out of the way. */
.bar.on .bar-in {
    border-color: var(--line);
    background: linear-gradient(180deg, rgba(12, 19, 35, 0.94), rgba(8, 13, 24, 0.96));
    box-shadow: var(--shadow), inset 0 1px 0 var(--sheen);
    -webkit-backdrop-filter: blur(22px) saturate(1.3);
    backdrop-filter: blur(22px) saturate(1.3);
}

.brand {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    flex: none;
    font-size: 1.16rem;
    font-weight: 700;
    letter-spacing: -0.02em;
}

.brand img { width: 30px; height: 30px; object-fit: contain; }

.brand small {
    display: block;
    margin-top: -2px;
    font-size: 0.6rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--faint);
}

.nav {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: auto;
}

.nav a {
    padding: 0.5rem 0.8rem;
    border-radius: var(--r-xs);
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--sub);
    transition: color 0.16s, background 0.16s;
}

.nav a:hover { color: var(--txt); background: var(--hover); }

.bar-cta { flex: none; }

/* Hamburger. Hidden on desktop; it is the only control that appears at the
   narrow end, where the six nav links cannot fit beside the wordmark. */
.burger {
    display: none;
    width: 2.6rem;
    height: 2.6rem;
    margin-left: auto;
    padding: 0;
    border: 1px solid var(--line-hi);
    border-radius: var(--r-xs);
    background: rgba(8, 14, 26, 0.6);
    color: var(--txt);
    cursor: pointer;
}

.burger svg { width: 1.15rem; height: 1.15rem; }

.burger .x, .burger[aria-expanded="true"] .m { display: none; }
.burger[aria-expanded="true"] .x { display: block; }

/* ============================== HERO ============================== */
.hero {
    padding-top: calc(var(--bar) + clamp(28px, 5vw, 64px));
    padding-bottom: clamp(56px, 7vw, 96px);
}

/* Not 50/50. The headline is the widest thing on the page and the console
   drawing is happy small, so the text column takes the extra: at an even
   split the second line of the heading wrapped and left "end." alone on a
   third line, which reads as a mistake rather than a line break. */
.hero-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
    gap: clamp(36px, 5vw, 68px);
    align-items: center;
}

/* A chip, not a badge: same geometry as the sign-in screen's `.fact i`
   surface (--chip fill, sky ink), stretched to hold a line of text. */
.chip {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.4rem 0.85rem 0.4rem 0.5rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--chip);
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--sub);
}

.chip b { color: var(--txt); font-weight: 600; }

.chip .dot {
    width: 0.5rem;
    height: 0.5rem;
    margin-left: 0.25rem;
    border-radius: 50%;
    background: var(--acc);
    box-shadow: 0 0 0 4px rgba(0, 234, 194, 0.14);
    animation: pulse 2.4s ease-in-out infinite;
}

@keyframes pulse {
    0%, 100% { box-shadow: 0 0 0 4px rgba(0, 234, 194, 0.14); }
    50% { box-shadow: 0 0 0 7px rgba(0, 234, 194, 0.05); }
}

/* The cap is set by the longest clause, not by taste: "supervised end to
   end." has to hold one line in the hero's text column at the wrap's full
   1180px, and 3.3rem is where it does with room to spare. */
.hero h1 {
    margin-top: 1.35rem;
    font-size: clamp(2.05rem, 4.4vw, 3.3rem);
    font-weight: 800;
    line-height: 1.06;
    letter-spacing: -0.035em;
    text-wrap: balance;
}

/* The gradient is on ONE clause, not the whole heading. The old page ran
   background-clip across the entire h1, which meant the sentence had no
   emphasis anywhere -- everything was highlighted, so nothing was. */
.hero h1 em {
    font-style: normal;
    background: linear-gradient(100deg, var(--acc), var(--acc2) 62%, #a99bff);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

.hero .lead { max-width: 34rem; font-size: clamp(1.02rem, 1.6vw, 1.17rem); }

.hero-cta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.85rem;
    margin-top: 2rem;
}

/* Four one-line claims under the buttons. Each is anchored to something the
   application actually does -- see the section comment in login.aspx that
   sets the same rule for its three. */
.hero-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem 1.6rem;
    margin-top: 2.1rem;
    padding-top: 1.7rem;
    border-top: 1px solid var(--line);
}

.fact {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    font-size: 0.85rem;
    color: var(--faint);
}

.fact svg { width: 1rem; height: 1rem; flex: none; color: var(--acc); }

/* ---------------------- HERO VISUAL ----------------------
   A stylised view of the supervisor console, drawn in CSS rather than
   screenshotted. Two reasons: a screenshot of a live jail system would carry
   real prisoner names and numbers, and a picture goes stale the moment the
   console is restyled while this is built from the same tokens and cannot.
   It is aria-hidden and captioned as illustrative -- it is a diagram of the
   product, and it does not pretend otherwise. */
.viz { position: relative; }

.viz-frame { padding: 0.85rem; border-radius: var(--r-lg); }

.viz-bar {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0 0.35rem 0.8rem;
}

.viz-dots { display: flex; gap: 0.3rem; }

.viz-dots i { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--line-hi); }

.viz-title {
    margin-left: 0.35rem;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--faint);
}

.viz-live {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-left: auto;
    padding: 0.2rem 0.55rem;
    border-radius: 999px;
    background: rgba(52, 227, 157, 0.12);
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ok);
}

.viz-live i {
    width: 0.38rem;
    height: 0.38rem;
    border-radius: 50%;
    background: var(--ok);
    animation: pulse 2.4s ease-in-out infinite;
}

/* ---------------------- LIVE STATS ----------------------
   Six real totals out of the Connecto database. The 1px grid gap over a
   --line background draws every divider as a single hairline shared between
   neighbours, so the block reads as one instrument panel rather than six
   cards that happen to be adjacent -- the same trick the capability band
   further down the page uses. */
.stats {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1px;
    margin: 0;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--line);
    overflow: hidden;
}

.stats > div { padding: 0.85rem 0.9rem; background: rgba(9, 15, 28, 0.92); }

.stats dt {
    font-size: 0.6rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--faint);
}

/* Tabular figures. Without them the six values are set in proportional
   digits, so "1,37,640" and "2,985" sit on visibly different rhythms and the
   right-hand column looks misaligned even though the boxes are identical. */
.stats dd {
    margin: 0.3rem 0 0;
    font-size: clamp(1.15rem, 2.4vw, 1.5rem);
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.05;
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

.stats dd.a { color: var(--acc); }
.stats dd.b { color: var(--acc2); }
.stats dd.c { color: var(--warn); }

.stats dd small {
    margin-left: 0.28rem;
    font-size: 0.58em;
    font-weight: 600;
    letter-spacing: 0;
    color: var(--faint);
}


.viz-cap {
    margin-top: 0.8rem;
    text-align: center;
    font-size: 0.72rem;
    color: var(--faint);
}

/* ============================== FACTS BAND ==============================
   Four capability statements, not invented metrics. A landing page for a
   system installed in a handful of facilities cannot honestly print
   "10M calls" -- so this band prints what the software does instead, which
   is both true and more useful to the officer reading it. */
.band {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1px;
    overflow: hidden;
    background: var(--line);
}

.band > div { padding: 1.5rem 1.4rem; background: rgba(10, 17, 32, 0.82); }

.band b {
    display: block;
    font-size: 1.42rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    background: linear-gradient(90deg, var(--acc), var(--acc2));
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

.band span { display: block; margin-top: 0.3rem; font-size: 0.86rem; color: var(--sub); }

/* ============================== GRID CARDS ============================== */
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 17.5rem), 1fr));
    gap: 1.1rem;
}

/* Flex column so the module line can be pushed to the bottom edge. Grid
   already stretches the cards in a row to equal height; without this the
   rule above each module line sits at a different height in every card and
   the row reads as ragged even though the boxes line up. */
.feat {
    display: flex;
    flex-direction: column;
    padding: 1.6rem;
    transition: transform 0.24s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.24s, box-shadow 0.24s;
}

.feat:hover {
    transform: translateY(-4px);
    border-color: rgba(0, 234, 194, 0.32);
    box-shadow: var(--shadow-lg), inset 0 1px 0 var(--sheen);
}

/* The icon chip from login.aspx's `.fact i`, at card scale. Sky ink on a
   10%-sky fill on every card: the icons are wayfinding, not decoration, so
   none of them competes with the teal reserved for actions. */
.ico {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.7rem;
    height: 2.7rem;
    margin-bottom: 1.05rem;
    border: 1px solid var(--line);
    border-radius: var(--r-xs);
    background: var(--chip);
    color: var(--acc2);
}

.ico svg { width: 1.25rem; height: 1.25rem; }

/* The bottom margin is the MINIMUM gap before the module line; `margin-top:
   auto` on that line eats whatever height is left over. Without the margin,
   the tallest card in a row -- the one with no slack for auto to absorb --
   would have its rule sitting flush against the last sentence. */
.feat p { margin-top: 0.55rem; margin-bottom: 0.95rem; font-size: 0.92rem; line-height: 1.68; color: var(--sub); }

.ico { flex: none; }

/* A closing line under a grid of cards. Deliberately plain and rule-marked
   rather than boxed: it is an aside to the section above it, and giving it a
   card of its own would make it compete with the claims it is closing. */
.note {
    max-width: 46rem;
    margin-top: 1.6rem;
    padding-left: 0.9rem;
    border-left: 2px solid var(--line-hi);
    font-size: 0.85rem;
    line-height: 1.7;
    color: var(--faint);
}

.note b { font-weight: 600; color: var(--acc2); }

/* The module each card corresponds to inside the console. It keeps the copy
   honest -- every claim on this page can be opened and pointed at. */
.feat .where {
    display: block;
    margin-top: auto;
    padding-top: 0.8rem;
    border-top: 1px solid var(--line);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    color: var(--faint);
}

/* ============================== STEPS ============================== */
.steps {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
    gap: 1.1rem;
    counter-reset: step;
}

.step { position: relative; padding: 1.55rem; }

.step::before {
    counter-increment: step;
    content: counter(step, decimal-leading-zero);
    display: block;
    margin-bottom: 0.85rem;
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.12em;
    color: var(--acc);
}

/* The thread between steps. Drawn only where a next step exists on the same
   row, and dropped entirely once the grid stacks. */
.step::after {
    content: "";
    position: absolute;
    top: 2.35rem;
    right: -1.1rem;
    width: 1.1rem;
    height: 1px;
    background: linear-gradient(90deg, var(--line-hi), transparent);
}

.step:last-child::after { display: none; }

.step p { margin-top: 0.5rem; font-size: 0.9rem; line-height: 1.66; color: var(--sub); }

/* ============================== SPLIT ============================== */
.split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(32px, 4.5vw, 60px);
    align-items: center;
}

/* A checklist built from the sign-in screen's `.fact` row, one size up. */
.list { display: grid; gap: 0.7rem; }

.list li {
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
    padding: 0.95rem 1.05rem;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: rgba(8, 14, 26, 0.45);
    list-style: none;
}

.list svg { width: 1.05rem; height: 1.05rem; flex: none; margin-top: 0.2rem; color: var(--acc); }

.list b { display: block; font-size: 0.93rem; font-weight: 600; color: var(--txt); }

/* `b + span`, NOT a bare `span`. Each row is <span><b>title</b><span>detail
   </span></span> -- one wrapper so the icon and the text sit as two flex
   children rather than three. A bare `.list span` therefore matched the
   WRAPPER too and painted the whole row --faint, title included, which read
   as every one of these being secondary text. */
.list b + span { display: block; margin-top: 0.15rem; font-size: 0.85rem; line-height: 1.6; color: var(--faint); }

ul.list, ol.list { margin: 0; padding: 0; }

/* ============================== AUDIENCE ============================== */
.who { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 13.5rem), 1fr)); gap: 1.1rem; }

.who div { padding: 1.35rem; }

.who h3 { font-size: 0.98rem; }

.who p { margin-top: 0.4rem; font-size: 0.87rem; line-height: 1.62; color: var(--sub); }

.who .ico { width: 2.3rem; height: 2.3rem; margin-bottom: 0.9rem; }

.who .ico svg { width: 1.1rem; height: 1.1rem; }

/* ============================== PRIME ==============================
   The companion app. This was one wide card with the copy on the left, six
   bare labels under it and a small slab on the right; it read as a footnote
   to the page rather than a second product. It is now a section of its own,
   with its own wash, real feature blocks and a handset drawn properly.

   `auto` on the second column, not a fraction: the device is a fixed-width
   object, and giving it a share of the row would stretch the frame around
   the screen instead of giving the copy the extra space. */
.prime-sec { overflow: hidden; }

/* Its own light, pulled toward the device so the handset sits in a pool
   rather than on a flat field. Same two accents as everywhere else. */
.prime-sec::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background:
        radial-gradient(38vw 38vw at 88% 42%, rgba(0, 234, 194, 0.10), transparent 64%),
        radial-gradient(34vw 34vw at 6% 88%, rgba(111, 202, 248, 0.08), transparent 62%);
}

.prime {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: clamp(34px, 5vw, 70px);
    align-items: center;
}

/* Platform line. Chips, not store badges -- Connecto Prime is issued to a
   facility, not downloaded off a shelf, so a Play Store button would promise
   something that is not there. */
.stores {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 1.5rem;
}

.stores span {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.42rem 0.8rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--chip);
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--sub);
}

.stores svg { width: 0.95rem; height: 0.95rem; color: var(--acc2); }

/* Fixed two-up, not auto-fit. There are exactly FOUR of these, and auto-fit
   was packing three across the copy column and leaving the fourth alone on a
   row next to a hole the width of two blocks. Four items want 2x2. */
.prime-feats {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1.6rem 1.9rem;
    margin-top: 2.1rem;
    padding-top: 1.9rem;
    border-top: 1px solid var(--line);
}

.prime-feats .ico { width: 2.5rem; height: 2.5rem; margin-bottom: 0.8rem; }

.prime-feats .ico svg { width: 1.15rem; height: 1.15rem; }

.prime-feats h3 { font-size: 0.95rem; }

.prime-feats p { margin-top: 0.35rem; font-size: 0.86rem; line-height: 1.62; color: var(--sub); }

/* ------------------------------ DEVICE ------------------------------ */
.device {
    position: relative;
    width: 274px;
    flex: none;
    padding: 11px;
    border: 1px solid rgba(140, 170, 255, 0.22);
    border-radius: 38px;
    background: linear-gradient(160deg, #171f33, #0a1020 42%, #070c17);

    /* Two rims and a drop: the outer hairline is the chassis edge, the inset
       highlight is the light running along it, and the shadow puts the whole
       thing above the section. Without the inset the frame reads as a flat
       dark rectangle with rounded corners. */
    box-shadow:
        0 2.4rem 4.2rem -1.4rem rgba(0, 0, 0, 0.85),
        inset 0 1px 0 rgba(255, 255, 255, 0.10),
        inset 0 0 0 1px rgba(0, 0, 0, 0.5);
}

/* Power button on the right edge. One small asymmetry is what stops the
   drawing reading as a rounded rectangle and starts it reading as hardware. */
.device-btn.side {
    position: absolute;
    right: -2px;
    top: 6.2rem;
    width: 2px;
    height: 2.6rem;
    border-radius: 2px;
    background: rgba(140, 170, 255, 0.3);
}

.device-screen {
    position: relative;
    padding: 0.55rem 0.6rem 0.5rem;
    border-radius: 29px;
    background: linear-gradient(180deg, #080e1b, #060a13);
    overflow: hidden;
}

.device-status {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.15rem 0.45rem 0.5rem;
    font-size: 0.62rem;
    font-weight: 700;
    color: var(--sub);
}

/* Signal bars and a battery, built from four <i> and a <b>. Cheaper than an
   icon, and it is the detail that makes the top strip read as a phone. */
.device-status .sig { display: flex; align-items: flex-end; gap: 2px; }

.device-status .sig i {
    width: 2px;
    border-radius: 1px;
    background: var(--sub);
}

.device-status .sig i:nth-child(1) { height: 3px; }
.device-status .sig i:nth-child(2) { height: 5px; }
.device-status .sig i:nth-child(3) { height: 7px; }
.device-status .sig i:nth-child(4) { height: 9px; opacity: 0.35; }

.device-status .sig b {
    width: 14px;
    height: 8px;
    margin-left: 3px;
    border: 1px solid var(--sub);
    border-radius: 2px;
    background: linear-gradient(90deg, var(--acc) 62%, transparent 62%);
}

.device-top {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0 0.15rem 0.65rem;
}

.device-logo { display: flex; flex: none; }

.device-logo img { width: 22px; height: 22px; object-fit: contain; }

.device-who { flex: 1; min-width: 0; line-height: 1.25; }

.device-who b { display: block; font-size: 0.74rem; font-weight: 700; }

.device-who > span { display: block; font-size: 0.6rem; color: var(--faint); }

.device-top .viz-live { padding: 0.15rem 0.4rem; font-size: 0.55rem; }

/* The headline card. The one filled surface on the screen -- an app's home
   screen has a primary figure, and drawing everything at the same weight is
   what made the previous mock look like a list of chips. */
.device-hero {
    padding: 0.75rem 0.8rem;
    border: 1px solid rgba(0, 234, 194, 0.28);
    border-radius: 16px;
    background:
        radial-gradient(120% 140% at 0% 0%, rgba(0, 234, 194, 0.18), transparent 62%),
        linear-gradient(135deg, rgba(0, 234, 194, 0.10), rgba(111, 202, 248, 0.08));
}

.device-hero > span {
    font-size: 0.56rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--sub);
}

.device-hero b {
    display: block;
    margin-top: 0.15rem;
    font-size: 1.5rem;
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1.05;
    color: var(--acc);
    font-variant-numeric: tabular-nums;
}

.device-hero em { display: block; margin-top: 0.1rem; font-style: normal; font-size: 0.6rem; color: var(--faint); }

.device-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.4rem; margin-top: 0.4rem; }

.device-tiles > div {
    padding: 0.5rem 0.55rem;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: rgba(15, 23, 42, 0.6);
}

.device-tiles span {
    font-size: 0.53rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--faint);
}

.device-tiles b {
    display: block;
    margin-top: 0.15rem;
    font-size: 0.92rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--acc2);
    font-variant-numeric: tabular-nums;
}

.device-rows { display: grid; gap: 0.35rem; margin-top: 0.5rem; }

.device-rows > div {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 0.5rem;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: rgba(15, 23, 42, 0.45);
}

.device-rows .av {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    flex: none;
    border-radius: 8px;
    background: var(--chip);
    color: var(--acc2);
}

.device-rows .av svg { width: 0.78rem; height: 0.78rem; }

.device-rows .t { min-width: 0; line-height: 1.3; }

.device-rows .t b { display: block; font-size: 0.7rem; font-weight: 600; }

.device-rows .t span { display: block; font-size: 0.56rem; color: var(--faint); }

/* Bottom tab bar. An app is recognisable by this strip more than by anything
   above it, which is why it is worth the twenty lines. */
.device-tabs {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    margin: 0.6rem -0.6rem 0;
    padding: 0.5rem 0.6rem 0.15rem;
    border-top: 1px solid var(--line);
}

.device-tabs span { display: flex; align-items: center; justify-content: center; color: var(--faint); }

.device-tabs svg { width: 0.95rem; height: 0.95rem; }

.device-tabs .on { position: relative; color: var(--acc); }

.device-tabs .on::after {
    content: "";
    position: absolute;
    bottom: -0.28rem;
    left: 50%;
    transform: translateX(-50%);
    width: 1rem;
    height: 2px;
    border-radius: 2px;
    background: var(--acc);
}

/* Home indicator. */
.device-bar {
    display: block;
    width: 5.5rem;
    height: 3px;
    margin: 0.45rem auto 0.1rem;
    border-radius: 3px;
    background: rgba(233, 239, 253, 0.28);
}

/* ============================== PARTNER ============================== */
.partner {
    display: flex;
    align-items: center;
    gap: clamp(20px, 3vw, 40px);
    padding: clamp(24px, 3vw, 36px);
    flex-wrap: wrap;
}

/* The supplied mark is dark artwork on a light plate, which disappears on a
   navy page. A white plate under it is the honest fix -- a partner's logo
   should be shown as issued, not recoloured to match somebody else's theme. */
.partner-logo {
    flex: none;
    padding: 0.85rem 1.15rem;
    border-radius: var(--r-sm);
    background: #fff;
}

.partner-logo img { display: block; width: auto; height: 2.4rem; }

/* min() rather than a bare 15rem. The floor is there to stop the text column
   collapsing to a sliver beside the logo plate while both still fit on one
   row -- but on a 320px phone the card's content box is narrower than 15rem
   itself, so the floor became wider than its own parent and pushed 15px of
   the band off-screen. `min(..., 100%)` keeps the intent and cannot exceed
   the space available. */
.partner-txt { flex: 1; min-width: min(15rem, 100%); }

.partner-txt p { margin-top: 0.4rem; font-size: 0.92rem; line-height: 1.68; color: var(--sub); }

/* ============================== CTA ============================== */
.cta {
    position: relative;
    padding: clamp(40px, 6vw, 72px) clamp(24px, 4vw, 56px);
    border-radius: var(--r-lg);
    text-align: center;
    overflow: hidden;
}

/* The hero's own wash, tightened into the panel so the page closes on the
   colour it opened with. */
.cta::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background:
        radial-gradient(60% 120% at 15% 0%, rgba(0, 234, 194, 0.16), transparent 60%),
        radial-gradient(60% 120% at 85% 100%, rgba(111, 202, 248, 0.16), transparent 60%);
}

.cta h2 { max-width: 24rem; margin: 0 auto; }

.cta .lead { max-width: 34rem; margin-left: auto; margin-right: auto; }

.cta .hero-cta { justify-content: center; }

/* ============================== FOOTER ============================== */
.foot { border-top: 1px solid var(--line); padding: clamp(44px, 5vw, 64px) 0 2.25rem; }

.foot-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr));
    gap: clamp(28px, 4vw, 48px);
}

.foot-brand p { margin-top: 1rem; max-width: 24rem; font-size: 0.88rem; line-height: 1.7; color: var(--faint); }

.foot h4 {
    margin-bottom: 0.95rem;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--sub);
}

.foot ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 0.6rem; }

/* `anywhere`, not `break-word`. The contact column holds
   subhayanban1983@gmail.com -- one 25-character token with nothing in it a
   browser will break on. Between about 1040px and 1150px the four footer
   columns are narrow enough that it does not fit, and it pushed 15px out of
   its own column. Only `anywhere` also shrinks the item's min-content width,
   which is what the grid track measures itself against; `break-word` would
   wrap the text and leave the track just as wide. */
.foot li a, .foot li span {
    font-size: 0.88rem;
    color: var(--faint);
    overflow-wrap: anywhere;
    transition: color 0.16s;
}

.foot li a:hover { color: var(--acc); }

.foot-end {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem 1.5rem;
    align-items: center;
    justify-content: space-between;
    margin-top: clamp(32px, 4vw, 48px);
    padding-top: 1.6rem;
    border-top: 1px solid var(--line);
    font-size: 0.82rem;
    line-height: 1.7;
    color: var(--faint);
}

/* The floating back-to-top control parks over this corner, and the copyright
   line is the last thing on the page -- so on any viewport narrow enough that
   the content column reaches the right edge (roughly 1000-1250px, which is
   most laptops) the button sat on top of "All rights reserved". Reserve the
   width instead of hoping the two never meet. */
.foot-end > :last-child { padding-right: 4.25rem; }

.foot-end b { font-weight: 600; color: var(--sub); }

.foot-end a { color: var(--sub); }

.foot-end a:hover { color: var(--acc); }

/* ============================== BACK TO TOP ==========================
   Appears once the hero is behind you and rides the rest of the page.

   The ring around it is the scroll position, drawn as a conic gradient
   masked down to a 2px band -- so the control is not only a way back, it
   also answers "how much of this is left", which is the question that makes
   someone reach for it in the first place. `--p` is a plain percentage set
   by landing.js; with the script blocked the button never gains `.on` and
   stays hidden, which is correct -- an inert scroll button is worse than
   none, and the footer already carries links back to every section. */
.totop {
    position: fixed;
    right: clamp(16px, 2.4vw, 30px);
    bottom: clamp(16px, 2.4vw, 30px);
    z-index: 90;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3.25rem;
    height: 3.25rem;
    padding: 0;
    border: 1px solid rgba(0, 234, 194, 0.3);
    border-radius: 50%;

    /* Lit from above, like the primary button, so it reads as something to
       press. The old flat slate panel read as a dead chip parked in the
       corner -- present, but not obviously a control. */
    background:
        radial-gradient(125% 125% at 50% 0%, rgba(0, 234, 194, 0.18), transparent 62%),
        linear-gradient(180deg, rgba(14, 22, 40, 0.96), rgba(8, 13, 24, 0.98));
    color: var(--acc);

    /* Three layers: the drop shadow that lifts it off the page, the inset
       sheen every other surface here carries, and a teal bloom that keeps it
       findable over the light wash at the top of a section. */
    box-shadow:
        0 0.9rem 2.2rem -0.7rem rgba(0, 0, 0, 0.8),
        inset 0 1px 0 var(--sheen),
        0 0 1.8rem -0.5rem rgba(0, 234, 194, 0.45);
    -webkit-backdrop-filter: blur(22px) saturate(1.3);
    backdrop-filter: blur(22px) saturate(1.3);
    cursor: pointer;

    /* visibility, not just opacity: a fully transparent button still takes
       clicks and still stops at a Tab press, so over the hero this would be
       an invisible target sitting on top of the page. */
    opacity: 0;
    visibility: hidden;
    transform: translateY(0.6rem) scale(0.9);
    transition: opacity 0.25s ease, transform 0.25s cubic-bezier(0.16, 1, 0.3, 1),
                visibility 0.25s, border-color 0.18s, color 0.18s;
}

.totop.on { opacity: 1; visibility: visible; transform: none; }

.totop:hover {
    border-color: rgba(0, 234, 194, 0.6);
    color: #ffffff;
    box-shadow:
        0 1.1rem 2.6rem -0.7rem rgba(0, 0, 0, 0.85),
        inset 0 1px 0 var(--sheen),
        0 0 2.4rem -0.4rem rgba(0, 234, 194, 0.6);
}

.totop:active { transform: translateY(1px); }

.totop svg { width: 1.2rem; height: 1.2rem; stroke-width: 2; }

/* The progress band -- a conic sweep filled to --p percent, then masked down
   to a 3px ring. Two colour stops rather than one, so the ring runs teal into
   sky as it fills and matches the primary button's gradient instead of being
   a flat accent hoop. The third stop sits at position 0, which CSS resolves
   as "same place as the previous stop": that is what makes the fill end in a
   hard edge rather than fading into the track.

   Both mask spellings are required -- WebKit shipped only the prefixed one
   for years and Safari still reads it. */
.totop::before {
    content: "";
    position: absolute;
    inset: -5px;
    border-radius: 50%;
    background: conic-gradient(from -90deg,
        var(--acc),
        var(--acc2) calc(var(--p, 0) * 1%),
        rgba(140, 170, 255, 0.16) 0);
    -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
    mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
    pointer-events: none;
}

/* Says what it is, on hover and on keyboard focus. A lone arrow in a corner
   is a guess; two words are not. Suppressed where there is no hover, since a
   tooltip that can only be triggered by tapping the thing it describes is
   just a flash of text on the way to the top of the page. */
.totop::after {
    content: "Back to top";
    position: absolute;
    right: calc(100% + 0.6rem);
    top: 50%;
    transform: translateY(-50%) translateX(0.3rem);
    padding: 0.36rem 0.62rem;
    border: 1px solid var(--line-hi);
    border-radius: var(--r-xs);
    background: #0c1323;
    color: var(--sub);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.18s ease, transform 0.18s cubic-bezier(0.16, 1, 0.3, 1);
}

.totop:hover::after,
.totop:focus-visible::after { opacity: 1; transform: translateY(-50%) translateX(0); }

@media (hover: none) {
    .totop::after { display: none; }
}

/* Engines without mask would paint a filled teal disc over the button. Ask
   for the ring only where masking actually exists. */
@supports not ((-webkit-mask: radial-gradient(#000, #000)) or (mask: radial-gradient(#000, #000))) {
    .totop::before { display: none; }
}

/* ============================== REVEAL ==============================
   login.aspx's `rise`, applied on entry by landing.js. The class is added by
   script and the rule is scoped to `html.js`, so with JavaScript off or
   broken the page is fully visible rather than a column of invisible
   sections waiting for an observer that never ran. */
html.js .rv { opacity: 0; transform: translateY(1.1rem); }

html.js .rv.in {
    opacity: 1;
    transform: none;
    transition: opacity 0.55s cubic-bezier(0.16, 1, 0.3, 1), transform 0.55s cubic-bezier(0.16, 1, 0.3, 1);
}

/* ============================== RESPONSIVE ============================== */
@media (max-width: 1040px) {
    .hero-grid { grid-template-columns: minmax(0, 1fr); }
    .viz { max-width: 34rem; margin: 0 auto; }
    .band { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .foot-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

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

    /* The handset drops below the copy and centres. It keeps its fixed width
       -- a phone that grows to fill a tablet stops looking like a phone. */
    .prime { grid-template-columns: minmax(0, 1fr); }
    .prime .device { justify-self: center; }
}

/* The bar collapses here: six links plus a wordmark plus a button stop
   fitting on one 64px row, and the links are what give way. */
@media (max-width: 860px) {
    :root { --gut: 18px; }

    .burger { display: flex; align-items: center; justify-content: center; }

    /* Fully opaque, and no backdrop-filter. Everywhere else on this page a
       translucent surface is the point; here it is a defect. The panel drops
       over the first card of whatever section is behind it, and at 0.97 alpha
       over a blurred backdrop that card's heading still read through the menu
       clearly enough to compete with the links. A navigation menu has one job
       and it is legibility, so this surface is solid. */
    .nav {
        position: absolute;
        top: calc(100% + 8px);
        left: 0;
        right: 0;
        display: none;
        flex-direction: column;
        align-items: stretch;
        gap: 0.2rem;
        padding: 0.7rem;
        border: 1px solid var(--line-hi);
        border-radius: 18px;
        background: linear-gradient(180deg, #0c1323, #080d18);
        box-shadow: var(--shadow-lg);
    }

    .nav.open { display: flex; }

    .nav a { padding: 0.75rem 0.9rem; font-size: 0.95rem; }

    .bar-in { position: relative; }

    /* The bar has to carry its own surface once the menu can drop out of it,
       or the panel hangs off something invisible. */
    .bar .bar-in {
        border-color: var(--line);
        background: linear-gradient(180deg, rgba(12, 19, 35, 0.9), rgba(8, 13, 24, 0.94));
        -webkit-backdrop-filter: blur(22px) saturate(1.3);
        backdrop-filter: blur(22px) saturate(1.3);
    }

    /* Sign-in stays reachable at every width -- it is the reason the page
       exists -- but it gives up its label for the icon at the narrow end. */
    .bar-cta .btn { padding: 0 0.9rem; }
    .bar-cta .btn span { display: none; }
}

@media (max-width: 620px) {
    .band { grid-template-columns: minmax(0, 1fr); }
    .foot-grid { grid-template-columns: minmax(0, 1fr); }
    .prime-feats { grid-template-columns: minmax(0, 1fr); }

    /* Clear the floating button, which is 3.25rem tall on a 1rem inset. On a
       narrow screen the footer's last line runs the full width, so horizontal
       padding alone no longer keeps the two apart. */
    .foot { padding-bottom: 4.75rem; }

    /* Trimmed on a phone, where a floating control covers a real share of the
       column it is floating over. 2.9rem is 46px -- still above the 44px
       minimum touch target, so it gives up presence and not usability. */
    .totop { width: 2.9rem; height: 2.9rem; right: 14px; bottom: 14px; }
    .totop svg { width: 1.05rem; height: 1.05rem; }
    .hero-cta .btn { width: 100%; }
    .viz-tiles { grid-template-columns: minmax(0, 1fr); }
    .step::after { display: none; }
    .brand small { display: none; }
}

/* ============================== MOTION ============================== */
@media (prefers-reduced-motion: reduce) {
    body::before, .chip .dot, .viz-live i, .wave i { animation: none; }

    html.js .rv { opacity: 1; transform: none; }

    .btn, .feat, .bar-in, .totop { transition: none; }

    .feat:hover { transform: none; }

    /* It still appears and disappears -- it just does it at once. The scroll
       it performs is switched to `auto` in landing.js for the same reason. */
    .totop { transform: none; }
}

/* ============================== PRINT ==============================
   Someone will print this to put in a file. Give them the words on white
   rather than eleven pages of navy. */
@media print {
    body::before, .bar, .viz, .cta::before, .totop { display: none !important; }

    body { background: #fff; color: #000; }

    .card, .list li, .band > div { border-color: #ccc; background: #fff; box-shadow: none; }

    .hero h1 em, .band b { -webkit-text-fill-color: #000; color: #000; }

    .sec { padding: 18px 0; }
}
