/* ==========================================================================
   Remote Nexus, LLC — brochure site
   Rebuilt from 2026.07.31_RemNex_Mockup_Webpage_02.pptx

   Palette + geometry are lifted from the deck:
     - Office accent1 #4472C4 is the brand blue. The body field on the Home
       and Technology pages is that colour as a circular gradient with its
       focus below the panel (PowerPoint: fillToRect l=50% t=130% b=-30%),
       running light -> mid -> deep from that focus outward.
     - Header band is white, 126/720 of the 1280x720 canvas.
     - Display face is Sitka Banner; body copy inherits the Office minor
       font, Calibri. Both are Windows/Office faces, so each has a stack.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Brand blue and the three gradient stops derived from it.
     #4472C4 is hsl(218.5 52% 51.8%); the stops are that hue at the
     luminance modifiers the deck specifies (lumMod 40/lumOff 60,
     lumMod 95/lumOff 5, lumMod 60). */
  --blue: #4472c4;
  --blue-tint: #b3c7e8;
  --blue-mid: #5b85cc;
  --blue-deep: #264478;
  --blue-ink: #1b3157;

  --paper: #ffffff;
  --ink: #16202e;
  --ink-soft: #3d4c63;
  --rule: rgba(38, 68, 120, 0.14);
  --link: #0563c1;

  /* Sitka ships with Windows/Office, so the deck renders natively there.
     Charter / Iowan / Georgia are the closest widely-available stand-ins.
     See README if you'd rather self-host a webfont for identical rendering
     on macOS, iOS and Android. */
  --font-display: "Sitka Banner", "Sitka Heading", "Sitka Subheading", Sitka,
    "Source Serif 4", "Source Serif Pro", Charter, "Bitstream Charter",
    "Iowan Old Style", Georgia, "Times New Roman", serif;
  --font-body: Calibri, Carlito, "Segoe UI", system-ui, -apple-system,
    "Helvetica Neue", Arial, sans-serif;

  /* The deck canvas is 1280px wide; keeping that as the measure means the
     proportions in the mockup survive translation. */
  --wrap: 1280px;
  --gutter: clamp(1.25rem, 3.5vw, 3rem);
  --header-h: clamp(76px, 9.8vw, 126px);

  --step-nav: clamp(1rem, 1.45vw, 1.35rem);
  --step-body: clamp(1rem, 0.95rem + 0.3vw, 1.19rem);
  --step-lead: clamp(1.9rem, 3.6vw, 3rem);
  --step-h2: clamp(1.5rem, 2.4vw, 2.1rem);

  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  font-family: var(--font-body);
  font-size: var(--step-body);
  line-height: 1.62;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

a {
  color: var(--link);
}

h1,
h2,
h3 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.16;
  margin: 0;
  text-wrap: balance;
}

p {
  margin: 0 0 1.15em;
}

p:last-child {
  margin-bottom: 0;
}

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

:where(a, button, input, textarea, summary):focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 3px;
  border-radius: 2px;
}

/* --------------------------------------------------------------------------
   3. Header + navigation
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--paper);
  /* The deck has a hard white-to-blue edge, which leaves the header
     invisible on the white pages. A hairline keeps it defined everywhere. */
  border-bottom: 1px solid var(--rule);
}

.header-inner {
  min-height: var(--header-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

.brand {
  display: flex;
  align-items: center;
  gap: clamp(0.6rem, 1.1vw, 1rem);
  text-decoration: none;
  color: var(--ink);
  flex-shrink: 0;
}

.brand__mark {
  width: auto;
  height: clamp(46px, 6.4vw, 82px);
}

.brand__name {
  display: flex;
  flex-direction: column;
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1.62vw, 1.5rem);
  line-height: 1.08;
  letter-spacing: 0.005em;
  white-space: nowrap;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.6vw, 2.6rem);
}

.site-nav a {
  position: relative;
  font-family: var(--font-display);
  font-size: var(--step-nav);
  color: var(--blue-ink);
  text-decoration: none;
  padding: 0.4em 0.1em;
  white-space: nowrap;
}

/* Underline grows from the left on hover; the current page keeps it on. */
.site-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.12em;
  height: 2px;
  background: var(--blue);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.32s var(--ease);
}

.site-nav a:hover::after,
.site-nav a:focus-visible::after {
  transform: scaleX(1);
}

/* Active page. The deck marks the current page with an invisible rectangle
   over its nav item (it blocks the click); a visible state is friendlier. */
body[data-page="company"] .site-nav [data-nav="company"],
body[data-page="technology"] .site-nav [data-nav="technology"],
body[data-page="services"] .site-nav [data-nav="services"],
body[data-page="contact"] .site-nav [data-nav="contact"] {
  color: var(--blue);
}

body[data-page="company"] .site-nav [data-nav="company"]::after,
body[data-page="technology"] .site-nav [data-nav="technology"]::after,
body[data-page="services"] .site-nav [data-nav="services"]::after,
body[data-page="contact"] .site-nav [data-nav="contact"]::after {
  transform: scaleX(1);
}

.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: var(--paper);
  cursor: pointer;
  color: var(--blue-ink);
}

.nav-toggle span,
.nav-toggle span::before,
.nav-toggle span::after {
  display: block;
  width: 20px;
  height: 2px;
  background: currentColor;
  margin-inline: auto;
  transition: transform 0.3s var(--ease), top 0.3s var(--ease),
    opacity 0.2s linear, background-color 0.2s linear;
}

.nav-toggle span::before,
.nav-toggle span::after {
  content: "";
  position: relative;
}

.nav-toggle span::before {
  top: -6px;
}

.nav-toggle span::after {
  top: 4px;
}

/* Open state: hide the middle bar and cross the outer two.
   ::before sits at -6px and ::after at +4px when closed; bringing both to
   the centre line (0 and -2px) and rotating them makes a true X. */
.nav-toggle[aria-expanded="true"] span {
  background: transparent;
}

.nav-toggle[aria-expanded="true"] span::before {
  top: 0;
  transform: rotate(45deg);
}

.nav-toggle[aria-expanded="true"] span::after {
  top: -2px;
  transform: rotate(-45deg);
}

/* --------------------------------------------------------------------------
   4. Panels
   -------------------------------------------------------------------------- */

/* Every page is a field panel now, and the short ones (Company, Contact) don't
   fill the viewport on their own. Letting the panel grow stops the white body
   from showing as a band above the footer. */
main {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}

.panel {
  position: relative;
  padding-block: clamp(2.5rem, 5.2vw, 4.5rem);
  flex: 1 0 auto;
}

/* The blue field from the deck: circular gradient, focus at 50% / 130%.

   The focus sits below the panel, so the brightest part of the field is the
   bottom centre — around #87a6da, where white body copy falls to roughly
   2.6:1 and fails. That was survivable while only the Home hero and Technology
   used this, since their lower halves are pictures. Now that prose, a form and
   its labels run to the foot of the page, the linear layer darkens the bottom
   just enough to carry small text (~6:1 at the very bottom). It's inert above
   40%, so the top of every panel is exactly as it was. */
.panel--field {
  background: linear-gradient(
      to bottom,
      rgba(12, 28, 58, 0) 40%,
      rgba(12, 28, 58, 0.5) 100%
    ),
    radial-gradient(
      118% 128% at 50% 130%,
      var(--blue-tint) 0%,
      var(--blue-mid) 46%,
      var(--blue-deep) 100%
    );
  color: var(--paper);
  overflow: clip;
}

/* Concentric rings radiating from the gradient focus — a quiet nod to the
   vibration field the hardware actually measures. Kept near-threshold. */
.panel--field::before {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-radial-gradient(
    circle at 50% 130%,
    rgba(255, 255, 255, 0.06) 0 1px,
    transparent 1px 82px
  );
  pointer-events: none;
}

.panel--field > * {
  position: relative;
}

/* Buttons carry their own colours — don't let the panel link colour win
   on specificity and paint a white label onto a white button. */
.panel--field a:not(.btn) {
  color: #dce8fb;
}

/* Pages with little content leave the field mostly empty. Centring their
   column vertically stops the copy clinging to the top of a tall blue panel.
   Safe against the usual flex-centring overflow trap: main and the panel both
   grow with their content, so there is never a taller-than-container case that
   would push the top out of reach. */
.panel--center {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Successive blocks inside one field panel. Keeping them in a single panel
   avoids a seam where two independent radial gradients would butt up. */
.tech-block + .tech-block {
  margin-top: clamp(2.75rem, 5.4vw, 4.5rem);
  padding-top: clamp(2.75rem, 5.4vw, 4.5rem);
  border-top: 1px solid rgba(255, 255, 255, 0.22);
}

/* --------------------------------------------------------------------------
   5. Home
   -------------------------------------------------------------------------- */

.hero {
  min-height: calc(100vh - var(--header-h));
  display: grid;
  align-items: center;
  padding-block: clamp(2.5rem, 5vw, 4rem);
}

.hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.06fr);
  align-items: center;
  gap: clamp(2rem, 5vw, 4.5rem);
}

.hero__lead {
  font-family: var(--font-display);
  font-size: var(--step-lead);
  line-height: 1.2;
  color: var(--paper);
  /* The deck sets this sentence 36pt in a 422px column — about 18 characters
     to the line. Matching the measure keeps the same rag. */
  max-width: 18ch;
  margin: 0;
  text-wrap: balance;
}

.hero__actions {
  margin-top: 2rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
}

.hero__figure {
  margin: 0;
  border-radius: 3px;
  overflow: hidden;
  box-shadow: 0 24px 60px -22px rgba(9, 22, 46, 0.75),
    0 0 0 1px rgba(255, 255, 255, 0.16);
}

.hero__figure img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

/* --------------------------------------------------------------------------
   6. Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.2vw, 1.15rem);
  padding: 0.68em 1.5em;
  border: 1px solid transparent;
  border-radius: 3px;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.22s var(--ease), background-color 0.22s var(--ease),
    border-color 0.22s var(--ease), color 0.22s var(--ease);
}

.btn:hover {
  transform: translateY(-2px);
}

.btn--solid {
  background: var(--paper);
  color: var(--blue-deep);
}

.btn--solid:hover {
  background: #eaf1fd;
}

.btn--ghost {
  border-color: rgba(255, 255, 255, 0.55);
  color: var(--paper);
}

.btn--ghost:hover {
  border-color: var(--paper);
  background: rgba(255, 255, 255, 0.1);
}


/* --------------------------------------------------------------------------
   7. Section furniture — headings, prose measure, and the framed-image card
   -------------------------------------------------------------------------- */

.section-head {
  max-width: 62ch;
  margin-bottom: clamp(1.75rem, 3.4vw, 2.75rem);
}

.eyebrow {
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--blue);
  margin: 0 0 0.7rem;
}

.panel--field .eyebrow {
  color: #cfe0fb;
}

.section-head h1,
.section-head h2 {
  font-size: var(--step-h2);
}

.prose {
  max-width: 68ch;
}

/* Statement-sized prose for a page that is copy and nothing else. The measure
   is in ch so it tracks the type size and holds around 54 characters a line —
   68ch at this size would run far past a comfortable read. Text stays
   ragged-right: centring multi-line paragraphs costs more in legibility than
   it returns in symmetry, so it's the column that's centred, not the words. */
.prose--lead {
  max-width: 54ch;
  margin-inline: auto;
  font-size: clamp(1.15rem, 1.02rem + 0.6vw, 1.55rem);
  line-height: 1.5;
}

.prose--lead .eyebrow {
  margin-bottom: 1.1rem;
}

/* Every framed image on the site — Company, Technology — is the same card:
   hairline ring, lifted shadow, caption bar across the foot. Only the palette
   differs between the paper and field panels, so the panel sets the tokens
   and the card just reads them. */
.figure-card {
  --fig-bg: var(--paper);
  --fig-shadow: 0 18px 44px -20px rgba(16, 33, 66, 0.55);
  --fig-ring: rgba(38, 68, 120, 0.12);
  --fig-cap-fg: var(--ink-soft);
  --fig-cap-bg: #f4f7fd;

  margin: 0;
  border-radius: 3px;
  overflow: hidden;
  background: var(--fig-bg);
  box-shadow: var(--fig-shadow), 0 0 0 1px var(--fig-ring);
}

.panel--field .figure-card {
  --fig-bg: rgba(255, 255, 255, 0.06);
  --fig-shadow: 0 20px 48px -22px rgba(6, 18, 40, 0.8);
  --fig-ring: rgba(255, 255, 255, 0.18);
  --fig-cap-fg: rgba(255, 255, 255, 0.82);
  --fig-cap-bg: rgba(11, 28, 56, 0.4);
}

.figure-card img {
  width: 100%;
}

.figure-card figcaption {
  font-size: 0.86rem;
  letter-spacing: 0.04em;
  padding: 0.7rem 0.9rem;
  color: var(--fig-cap-fg);
  background: var(--fig-cap-bg);
}

/* Short scannable list, used on Technology and Contact. Square markers rather
   than discs — the site is otherwise all straight rules and flat panels. The
   marker takes currentColor, so it reads on the paper and field palettes
   alike. */
.feature-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.55rem;
}

.feature-list li {
  position: relative;
  padding-left: 1.55rem;
}

.feature-list li::before {
  content: "";
  position: absolute;
  left: 0.15rem;
  top: 0.6em;
  width: 7px;
  height: 7px;
  background: currentColor;
  opacity: 0.5;
  transform: rotate(45deg);
}

/* --------------------------------------------------------------------------
   8. Company — narrative only; the page is a single prose column.
   -------------------------------------------------------------------------- */

.company__cta {
  margin-top: 1.75rem;
}

/* --------------------------------------------------------------------------
   9. Technology
   -------------------------------------------------------------------------- */

/* The three blocks on this page are the same grid at different proportions,
   so the shared half lives here and each block sets only its own columns. */
.tech-grid {
  display: grid;
  gap: clamp(1.75rem, 3.6vw, 3.25rem);
  align-items: start;
}

/* The right-hand column is much the tallest; centring the short ones spreads
   the slack instead of leaving a hole under them. */
.tech-problem {
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.05fr) minmax(0, 1.1fr);
  align-items: center;
}

.tech-rn3 {
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.35fr) minmax(0, 0.95fr);
}

/* Prose beside the capability list, with the screenshot spanning underneath.
   The app shot is 2:1 and full of fine UI text — in a half-column it renders
   about 600px wide and nothing in it reads, so it gets the full wrap. */
.tech-app {
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
}

.tech-app__shots {
  margin-top: clamp(1.75rem, 3.6vw, 3.25rem);
}

/* Screenshot slideshow. Unenhanced it is a plain stack of figures, which is a
   perfectly good page on its own; site.js sets data-enhanced and the slides
   collapse into a single crossfaded stage. Nothing here depends on JS having
   run, so a visitor without it loses the cycling and keeps the content. */
.slideshow {
  display: grid;
  gap: clamp(0.75rem, 1.6vw, 1.15rem);
}

.slideshow[data-enhanced="true"] {
  gap: 0;
}

/* Every slide occupies the same grid cell, so the container is as tall as its
   tallest member and the page never reflows as the deck cycles. */
.slideshow[data-enhanced="true"] .slideshow__slide {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.6s var(--ease), visibility 0s linear 0.6s;
}

.slideshow[data-enhanced="true"] .slideshow__slide[data-active="true"] {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.6s var(--ease), visibility 0s;
}

/* The captures don't share a ratio — the home screen is 2.08:1, the two
   spectrum views are square. Pinning the image height and letting `contain`
   settle the width keeps the stage one fixed size for every slide. The
   backdrop is the application's own near-black, so the margin either side of
   a square slide reads as screen rather than as a hole. */
.slideshow[data-enhanced="true"] .slideshow__slide img {
  height: clamp(240px, 40vw, 560px);
  object-fit: contain;
  background: #0b1119;
}

/* Captions run to different lengths; reserving two lines stops the controls
   beneath them from hopping as the deck advances. */
.slideshow[data-enhanced="true"] figcaption {
  min-height: 4.2rem;
}

.slideshow__controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  margin-top: 0.9rem;
}

.slideshow__dots {
  display: flex;
  gap: 0.5rem;
}

/* Bars rather than circles, to match the flat rules used elsewhere. */
.slideshow__dot {
  width: 34px;
  height: 6px;
  padding: 0;
  border: 0;
  border-radius: 1px;
  background: rgba(255, 255, 255, 0.28);
  cursor: pointer;
  transition: background-color 0.3s var(--ease);
}

.slideshow__dot:hover {
  background: rgba(255, 255, 255, 0.55);
}

.slideshow__dot[aria-current="true"] {
  background: var(--paper);
}

.slideshow__toggle {
  font: inherit;
  font-size: 0.86rem;
  letter-spacing: 0.04em;
  color: var(--paper);
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 3px;
  padding: 0.32rem 0.9rem;
  cursor: pointer;
  transition: border-color 0.22s var(--ease), background-color 0.22s var(--ease);
}

.slideshow__toggle:hover {
  border-color: var(--paper);
  background: rgba(255, 255, 255, 0.1);
}

.tech-col > * + * {
  margin-top: clamp(1.25rem, 2.4vw, 1.9rem);
}

/* Availability / sales card */
.callout {
  padding: clamp(1.15rem, 2vw, 1.6rem) clamp(1.25rem, 2.2vw, 1.75rem);
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.28);
  backdrop-filter: blur(2px);
}

.callout h3 {
  font-size: 1.16rem;
  margin-bottom: 0.5rem;
}

.callout__mail {
  display: inline-block;
  margin-top: 0.35rem;
  font-size: 1.06rem;
  color: var(--paper);
  text-decoration-color: rgba(255, 255, 255, 0.5);
  text-underline-offset: 4px;
}

/* --------------------------------------------------------------------------
   10. Services
   -------------------------------------------------------------------------- */

.services-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.62fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}

.pullquote {
  margin: 0;
  padding: clamp(1.4rem, 2.4vw, 2rem);
  border-left: 3px solid var(--blue);
  background: #f4f7fd;
  border-radius: 0 3px 3px 0;
}

.pullquote p {
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 1.7vw, 1.42rem);
  line-height: 1.4;
  color: var(--blue-ink);
}

.pullquote footer {
  margin-top: 0.9rem;
  font-size: 0.82rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* On the field the pale slab reads as a hole punched in the panel; the same
   translucent treatment the Availability callout uses sits on it properly. */
.panel--field .pullquote {
  background: rgba(255, 255, 255, 0.12);
  border-left-color: var(--paper);
}

.panel--field .pullquote p {
  color: var(--paper);
}

.panel--field .pullquote footer {
  color: rgba(255, 255, 255, 0.72);
}

/* --------------------------------------------------------------------------
   11. Contact form
   -------------------------------------------------------------------------- */

.contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}

.cform {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.35rem clamp(1.25rem, 2.6vw, 2.25rem);
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}

.field--wide {
  grid-column: 1 / -1;
}

.field label {
  font-weight: 700;
  font-size: 0.98rem;
  color: var(--ink);
}

.field .req {
  color: var(--blue);
}

/* The mockup's form is underline-only, so the inputs keep that treatment. */
.field input,
.field textarea {
  font: inherit;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-bottom: 1.5px solid var(--blue-deep);
  padding: 0.45rem 0.15rem;
  transition: border-color 0.22s var(--ease), box-shadow 0.22s var(--ease);
}

.field textarea {
  min-height: 7.5rem;
  resize: vertical;
}

.field input:hover,
.field textarea:hover {
  border-color: var(--blue);
}

.field input:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 2px 0 -0.5px var(--blue);
}

.field input[aria-invalid="true"],
.field textarea[aria-invalid="true"] {
  border-color: #b3261e;
}

.field .error {
  font-size: 0.86rem;
  color: #b3261e;
  min-height: 1.1em;
}

/* Submitting hands the enquiry to the visitor's own mail client (see
   site.js), which is a surprise if the button doesn't say so first. */
.cform__hint {
  grid-column: 1 / -1;
  margin: -0.4rem 0 0;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.cform__actions {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
}

.form-status {
  font-size: 0.95rem;
  color: var(--ink-soft);
}

.form-status[data-state="ok"] {
  color: #16653a;
}

.form-status[data-state="error"] {
  color: #b3261e;
}

.contact-aside {
  padding: clamp(1.4rem, 2.4vw, 2rem);
  background: #f4f7fd;
  border-radius: 3px;
  border: 1px solid var(--rule);
}

.contact-aside h2 {
  font-size: 1.25rem;
  margin-bottom: 0.75rem;
}

.contact-aside dl {
  margin: 0;
}

.contact-aside dt {
  font-size: 0.78rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-top: 1.1rem;
}

.contact-aside dd {
  margin: 0.25rem 0 0;
}

/* --------------------------------------------------------------------------
   11b. Contact form on the field panel. The form was drawn for dark ink on
        white paper: left alone here every label, rule and message would be
        dark-on-blue, and the aside would be white text on a near-white card.
   -------------------------------------------------------------------------- */

.panel--field .field label {
  color: var(--paper);
}

.panel--field .field .req {
  color: #9ec5ff;
}

.panel--field .field input,
.panel--field .field textarea {
  color: var(--paper);
  border-bottom-color: rgba(255, 255, 255, 0.45);
}

.panel--field .field input:hover,
.panel--field .field textarea:hover {
  border-bottom-color: rgba(255, 255, 255, 0.75);
}

.panel--field .field input:focus,
.panel--field .field textarea:focus {
  border-bottom-color: var(--paper);
  box-shadow: 0 2px 0 -0.5px var(--paper);
}

.panel--field .field input[aria-invalid="true"],
.panel--field .field textarea[aria-invalid="true"] {
  border-bottom-color: #ffb4ab;
}

.panel--field .field .error {
  color: #ffb4ab;
}

/* Chrome paints autofilled inputs pale blue with dark text and ignores
   `background`. Without this the filled fields become light boxes carrying
   white text on an otherwise transparent, underline-only form. */
.panel--field .field input:-webkit-autofill,
.panel--field .field input:-webkit-autofill:hover,
.panel--field .field input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--paper);
  -webkit-box-shadow: 0 0 0 1000px rgba(12, 28, 58, 0.9) inset;
  caret-color: var(--paper);
}

.panel--field .cform__hint {
  color: rgba(255, 255, 255, 0.78);
}

.panel--field .form-status {
  color: rgba(255, 255, 255, 0.82);
}

.panel--field .form-status[data-state="ok"] {
  color: #8ce0b0;
}

.panel--field .form-status[data-state="error"] {
  color: #ffb4ab;
}

.panel--field .contact-aside {
  background: rgba(255, 255, 255, 0.12);
  border-color: rgba(255, 255, 255, 0.28);
}

.panel--field .contact-aside dt {
  color: rgba(255, 255, 255, 0.72);
}

/* --------------------------------------------------------------------------
   12. Footer
   -------------------------------------------------------------------------- */

.site-footer {
  flex-shrink: 0;
  background: var(--blue-ink);
  color: rgba(255, 255, 255, 0.78);
  padding-block: clamp(1.75rem, 3.2vw, 2.5rem);
  font-size: 0.94rem;
}

.footer-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  align-items: center;
  justify-content: space-between;
}

.site-footer a {
  color: #dce8fb;
  text-underline-offset: 3px;
}

.footer-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
}

/* --------------------------------------------------------------------------
   13. Entrance motion — one staggered reveal per page load.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  .reveal {
    opacity: 0;
    transform: translateY(14px);
    animation: rise 0.7s var(--ease) forwards;
  }

  .reveal:nth-child(1) {
    animation-delay: 0.05s;
  }
  .reveal:nth-child(2) {
    animation-delay: 0.16s;
  }
  .reveal:nth-child(3) {
    animation-delay: 0.27s;
  }
  .reveal:nth-child(4) {
    animation-delay: 0.38s;
  }
}

@keyframes rise {
  to {
    opacity: 1;
    transform: none;
  }
}

/* Reveal elements start hidden, so make sure nothing can print blank. */
@media print {
  .reveal {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }
}

/* --------------------------------------------------------------------------
   14. Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 1080px) {
  .tech-problem,
  .tech-rn3 {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: start;
  }

  .tech-problem > :nth-child(3),
  .tech-rn3 > :nth-child(3) {
    grid-column: 1 / -1;
  }

  .services-body,
  .contact-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 860px) {
  .nav-toggle {
    display: grid;
    place-items: center;
  }

  .site-nav {
    position: absolute;
    inset-inline: 0;
    top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
    box-shadow: 0 18px 34px -20px rgba(16, 33, 66, 0.5);
    padding: 0.5rem var(--gutter) 1rem;
    display: none;
  }

  .site-nav[data-open="true"] {
    display: flex;
  }

  .site-nav a {
    padding: 0.85rem 0;
    border-bottom: 1px solid var(--rule);
  }

  .site-nav a::after {
    display: none;
  }

  .site-header {
    position: relative;
  }

  .hero {
    min-height: 0;
  }

  .hero__inner,
  .tech-problem,
  .tech-rn3,
  .tech-app {
    grid-template-columns: minmax(0, 1fr);
  }

  .hero__lead {
    max-width: 22ch;
  }

  /* Once the columns collapse, a figure at full container width is far
     bigger than it ever is in the mockup. The Company mosaic is two tiles
     wide, so it gets proportionally more room than a lone figure. */
  .panel--field .figure-card {
    max-width: 460px;
    margin-inline: auto;
  }

  /* Paired square screenshots land around 170px each on a phone, which is
     nothing. Stack them so every shot gets the whole column. */
  .tech-app__shots {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 560px) {
  .cform {
    grid-template-columns: minmax(0, 1fr);
  }

  .brand__name {
    font-size: 1rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
