/* Per-section layout, top to bottom. */

/* Nav: full-width bar, dayos pattern. The shell is transparent and spans the
   whole screen; the painted surfaces are the links capsule and the accent
   CTA. js/nav.js toggles .ground-dark/.ground-light on the header as the
   ground beneath the bar changes, which flips the wordmark, the capsule, and
   the toggle. The CTA is constant: black on mint reads on both grounds. */

.nav {
  position: sticky;
  top: 0;
  z-index: 10;
  height: var(--nav-height);
  display: flex;
  align-items: center;
  background: transparent;
}

.nav-bar {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  width: 100%;
  padding-inline: var(--space-3);
}

.wordmark {
  font-size: 1.5rem;
  letter-spacing: -0.01em;
  color: var(--color-carbon-black);
  transition: color 160ms ease;
}

.nav.ground-dark .wordmark {
  color: var(--color-paper-white);
}

/* The capsule. Centered in the bar independently of the asymmetric wordmark
   and CTA, like the reference. Opaque on the light ground; a raised dark
   surface on the slab. */
.nav-pill {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: var(--space-1);
  background: var(--surface-card);
  border-radius: var(--radius-pill);
  padding: 6px;
  transition: background-color 160ms ease;
}

.nav.ground-dark .nav-pill {
  background: #1f1f1f;
}

.nav-links a {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  font-size: var(--text-body);
  font-weight: 500;
  color: var(--color-slate);
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  transition: color 160ms ease, background-color 160ms ease;
}

.nav-links a:hover {
  color: var(--color-carbon-black);
  background: var(--color-mist-gray);
}

.nav.ground-dark .nav-links a {
  color: var(--color-ash);
}

.nav.ground-dark .nav-links a:hover {
  color: var(--color-paper-white);
  background: #2c2c2c;
}

.nav-end {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.nav .btn {
  padding: 12px 20px;
}

.btn-accent {
  background: var(--accent);
  color: var(--color-carbon-black);
  border-radius: var(--radius-button);
}

.btn-accent:hover {
  background: var(--color-paper-white);
}

/* Mobile nav toggle: hidden on desktop, a two-bar button beside the CTA on
   mobile. The links become a dropdown panel below the bar; the panel is a
   raised dark surface at every ground, so it needs no inversion logic. */

.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  min-width: 44px;
  min-height: 44px;
  padding: 12px;
  background: none;
  border: 0;
  cursor: pointer;
  align-items: center;
}

.nav-toggle-bar {
  width: 20px;
  height: 2px;
  background: var(--color-carbon-black);
  transition: background-color 160ms ease;
}

.nav.ground-dark .nav-toggle-bar {
  background: var(--color-paper-white);
}

@media (max-width: 900px) {
  .nav-toggle {
    display: flex;
  }

  .nav-links.nav-pill {
    display: none;
    position: absolute;
    top: calc(100% + 8px);
    left: var(--space-2);
    right: var(--space-2);
    transform: none;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: #141414;
    border-radius: var(--radius-card);
    padding: var(--space-2);
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45);
  }

  .nav-links.is-open {
    display: flex;
  }

  .nav-links a,
  .nav.ground-dark .nav-links a {
    display: block;
    min-height: 44px;
    padding: 12px 16px;
    color: var(--color-paper-white);
  }

  .nav-links a:hover,
  .nav.ground-dark .nav-links a:hover {
    color: var(--color-paper-white);
    background: #2c2c2c;
  }
}

/* Hero */

.hero {
  padding-block: var(--space-5) var(--space-10);
}

.hero-grid {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: var(--space-5);
  align-items: center;
}

.hero h1 {
  margin-bottom: var(--space-3);
}

.hero-sub {
  max-width: 34em;
  margin-bottom: var(--space-5);
}

.hero-ctas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* The loop video is transparent and floats directly on the canvas,
   the same compositing the reference site uses */
.hero-stage {
  /* PORTRAIT, not square. The stage was 1:1, which capped the tower at 473px
     inside an 800px hero -- the column read short and stubby when the whole
     point of the climbing render is height. A 3:4 box lets it run the hero's
     full height, and because the video is object-fit:contain the extra room
     goes into the column rather than stretching it. */
  aspect-ratio: 3 / 4;
  /* WIDTH-driven, height following the ratio. The height-driven form
     (height:100%; max-height:min(88vh,880px)) let the box's width outgrow its
     grid column at wide viewports -- measured: right edge at 1377px in a
     1360px viewport, a real page h-scroll. Width now can never exceed the
     column, and the 880px height cap survives as its width equivalent. */
  width: min(100%, calc(min(88vh, 880px) * 0.75));
  margin-inline: auto;
  /* The video inside is deliberately oversized (120%) with a negative margin
     so the column reads larger than its box. That overflows the page at
     narrower widths -- measured with tools/sweep.mjs, the page scrolled
     horizontally by 3px at 1240 because the video's right edge landed at
     1243. Clipping here keeps the oversize trick and stops the overflow. */
  overflow: hidden;
}

.hero-stage video {
  display: block;
  /* Fills the portrait stage exactly. The old 120% + -10% margin trick made
     the column read larger inside a square box; in a 3:4 box it just pushes
     the object out of frame at the sides, and the stage's own overflow:hidden
     would clip the column's flanks. */
  width: 100%;
  height: 100%;
  margin: 0;
  /* COVER with the crop steered to the SIDES, not the top.
     The render is square, the stage is portrait. `contain` letterboxes it back
     to 473px and undoes the height; plain `cover` crops symmetrically and eats
     the column's flanks, which widens the silhouette and loses the tower's
     shape. `object-position: center` keeps the vertical run intact -- the
     column is centred and far narrower than its 1000px plate, so what gets
     cropped is empty alpha at the left and right, which costs nothing.
     The scale below then pulls the column back to its true width. */
  object-fit: cover;
  object-position: center;
  /* The square render inside a 3:4 box is scaled by 4/3 to cover, which makes
     the column 33% wider than drawn. Scaling back on X restores its real
     proportion while the extra height stays. */
  transform: scaleX(0.75);
  transform-origin: center;
  /* THE MASK FADES BOTH ENDS, because this render is a different object.
     The previous hero's column stopped inside its frame and only needed its
     base dissolved, so a single bottom ramp from 70% was right. The climbing
     tower is painted edge to edge -- measured on the render, rows 0..999 of
     1000 carry pixels on every frame -- so the top cut hard against the page
     and the long bottom ramp read as haze rather than as recession.
     Short ramps at both ends: the column arrives from above and leaves below,
     and neither edge is a visible cut. */
  /* LONG ramps. The first pass used 7% and 12%, which is a cut with a soft
     edge rather than a fade -- at 473px that was 33px and 57px, too short for
     the eye to read as recession. 22% at each end gives the column real
     distance to dissolve into, so it arrives from somewhere and leaves for
     somewhere instead of stopping. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 22%,
                                      #000 78%, transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 22%,
                              #000 78%, transparent 100%);
}

/* ------------------------------------------------------------- grounds ----
   Two flat grounds and one hard seam, replacing the descent gradient. The
   hero sits on warm canvas; everything from the statements section down is
   one continuous black slab whose first section carries dayos-style rounded
   top corners against the light ground behind it (the body background).

   Flat colors keep tools/a11y.mjs exact: every zone's background-color IS
   the color behind its text, no pessimistic fallback needed. */

.zone-hero {
  background-color: var(--ground-light);
}

.zone-dark {
  background-color: var(--ground-dark);
  color: var(--color-paper-white);
}

/* The seam. Only the first dark section rounds its top; the sections after
   it share the same flat ground, so no visible join exists between them. */
.slab-top {
  border-radius: var(--radius-card-lg) var(--radius-card-lg) 0 0;
}

/* Cards are opaque white surfaces wherever they sit, so text inside them must
   re-anchor to dark ink -- without this, cards inside a dark zone inherit
   paper-white and render white-on-white (caught by tools/a11y.mjs on the
   work cards: contrast 1:1). */
.zone-dark .card {
  color: var(--color-carbon-black);
}

/* Accent moments on the slab. Mint on #060606 is 16.9:1; black on mint is
   17.9:1 (both computed), so the accent is safe as ground or as ink. */
::selection {
  background: var(--accent);
  color: var(--color-carbon-black);
}

.zone-dark a:focus-visible,
.zone-dark button:focus-visible,
.zone-dark [tabindex]:focus-visible {
  outline-color: var(--accent);
}

/* Sections shared */

.section {
  padding-block: var(--space-10);
}

.section-title {
  margin-bottom: var(--space-5);
}

/* Statements: the thesis in three columns, dayos's AI./GAP./CLOSED. shape.
   Display word over a short paragraph, nothing else. */

.statements-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-5);
}

.statement-word {
  margin-bottom: var(--space-3);
}

.statement p {
  color: var(--color-ash);
  max-width: 30em;
}

/* Services: full-bleed hairline rows. No imagery by request (Jon,
   2026-08-28: "Don't use the renders or images"), so the section wins on
   structure: title left, body right, rules running the full measure. */

.services-list {
  border-top: 1px solid var(--rule-dark);
}

.service-row {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: var(--space-5);
  align-items: start;
  padding-block: var(--space-8);
  border-bottom: 1px solid var(--rule-dark);
}

.service-title {
  font-family: var(--font-display);
  font-weight: 400;
  text-transform: uppercase;
  font-size: var(--text-heading);
  line-height: 1.05;
  letter-spacing: var(--tracking-heading);
}

.service-row p {
  color: var(--color-ash);
  max-width: 36em;
  line-height: 1.5;
}

/* The highlight: a mint rule grows on the row's leading edge and the content
   steps in from it. Both are geometry (scale and translate, compositor-only),
   so nothing reflows and the move reads at any contrast. */

.service-row::before {
  content: "";
  position: absolute;
  inset-block: var(--space-5);
  left: 0;
  width: 3px;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 240ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

.service-row:hover::before {
  transform: scaleY(1);
}

.service-title,
.service-row p {
  transition: transform 240ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

.service-row:hover .service-title,
.service-row:hover p {
  transform: translateX(var(--space-3));
}


/* Work */

.work-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
}

.work-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  overflow: hidden;
  padding: var(--space-2);
}

.work-shot {
  display: grid;
  place-items: center;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-card);
  overflow: hidden;
}

.work-shot img {
  transition: transform 300ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

a.work-shot:hover img {
  transform: scale(1.04);
}

/* Brand tiles: each venture's own ground (brand artwork, not system surfaces) */

.work-shot-aioss {
  background: #ffce1a;
}

.work-shot-aioss img {
  width: 68%;
}

.work-shot-pv {
  background: linear-gradient(135deg, #0b66ae, #12a0d7);
}

.work-shot-pv img {
  width: 52%;
}

.work-shot-scrapture {
  background: #141110;
}

.work-shot-scrapture img {
  width: 74%;
}

.work-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-2) var(--space-2);
}

.work-body h3 {
  text-transform: uppercase;
}

.work-body p {
  color: var(--color-slate);
  font-size: var(--text-body-sm);
  line-height: 1.4;
}

/* About (inverted) + contact dome */

.about {
  /* Ground comes from .zone-about; this keeps only the section's own shape. */
  padding-block: var(--space-12) var(--space-10);
}

.about-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-5);
}

/* The heading rides: sticky against the nav offset while the copy column
   scrolls past. Pure CSS, no scroll listener. Falls back to static in the
   single-column layout, where there is nothing to ride beside. */
.about-title {
  position: sticky;
  top: calc(var(--nav-height) + var(--space-2));
  align-self: start;
}

.about-copy {
  display: grid;
  gap: var(--space-3);
  /* White, not smoke: this zone starts at #707070, where smoke #979797 fails
     contrast outright (1.6:1). Hierarchy comes from weight, not from dimming. */
  color: var(--color-paper-white);
  font-size: var(--text-subheading);
  line-height: 1.5;
  align-content: start;
}

.about-copy strong {
  color: var(--color-paper-white);
  font-weight: 500;
}

.contact-wrap {
  /* Ground comes from .zone-connect. */
  padding-top: var(--space-8);
}

.contact-card {
  /* Inside a .zone-dark section, so color must be re-anchored: without this
     the card inherits paper-white text on a white card. */
  color: var(--color-carbon-black);
  background: var(--surface-card);
  border-radius: var(--radius-card-lg) var(--radius-card-lg) 0 0;
  padding: var(--space-12) var(--space-3) var(--space-10);
  text-align: center;
}

.contact-card h2 {
  max-width: 9em;
  margin-inline: auto;
}

.contact-card .line-wrap {
  width: fit-content;
  margin-inline: auto;
}

.contact-card .sub {
  max-width: 30em;
  margin: var(--space-3) auto var(--space-5);
}

/* Connect form. Lives inside the white .contact-card, so everything here is
   dark-on-white. Mechanism is contact-form.js's mailto handoff. */

.contact-form {
  display: grid;
  gap: var(--space-2);
  max-width: 34em;
  margin-inline: auto;
  text-align: left;
}

.contact-form .field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2);
}

.contact-form label {
  display: block;
  font-weight: 600;
  font-size: var(--text-body-sm);
  margin-bottom: 6px;
}

.contact-form input,
.contact-form textarea {
  width: 100%;
  font: inherit;
  color: var(--color-carbon-black);
  background: var(--color-mist-gray);
  border: 1px solid var(--color-ash);
  border-radius: var(--radius-card);
  padding: 12px 14px;
}

.contact-form input:focus-visible,
.contact-form textarea:focus-visible {
  outline: 2px solid var(--color-carbon-black);
  outline-offset: 1px;
}

.field-error {
  color: #a4262c;
  font-size: var(--text-body-sm);
  margin-top: 6px;
}

.contact-status {
  min-height: 1.4em;
  font-size: var(--text-body-sm);
  color: var(--color-slate);
}

.contact-form .btn {
  justify-self: start;
  margin-top: var(--space-1);
}

@media (max-width: 640px) {
  .contact-form .field-row {
    grid-template-columns: 1fr;
  }
}

/* Footer */

.footer {
  background: #000000;
  color: var(--color-smoke);
  padding-block: var(--space-5);
}

.footer-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  border-top: 1px solid var(--color-graphite);
  padding-top: var(--space-3);
}

/* Responsive */

@media (max-width: 900px) {
  .hero-grid,
  .statements-grid,
  .about-grid,
  .work-grid {
    grid-template-columns: 1fr;
  }

  .about-title {
    position: static;
  }

  /* Stacked rows: title over body. The hover highlight has no meaning on
     touch, so the marker and the offset are neutralized. */
  .service-row {
    grid-template-columns: 1fr;
    row-gap: var(--space-2);
    padding-block: var(--space-5);
  }

  .service-row:hover::before {
    transform: scaleY(0);
  }

  .service-row:hover .service-title,
  .service-row:hover p {
    transform: none;
  }

  .nav {
    height: 6rem;
  }

}



/* ---------------------------------------------------------------- a11y ----
   Both blocks were absent from this stylesheet and tools/a11y.mjs reported
   zero of each. They are floors this project set for itself, not additions. */

/* A visible focus ring for keyboard users. `:focus-visible` rather than
   `:focus` so a mouse click does not leave a ring behind. */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
  border-radius: 4px;
}

/* Honour a reduced-motion preference. The hero loop and the four process
   loops are decorative, so they hold their poster frame instead of playing
   (js/main.js), and scroll-triggered reveals resolve immediately rather than
   animating. The service-row hover states still resolve, just without
   travel, so the highlight remains legible. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .reveal {
    opacity: 1 !important;
    transform: none !important;
  }
}


/* The wordmark link measured 101x22 against tools/a11y.mjs's 32px floor.
   Padding expands the hit area without moving the glyphs: the nav uses
   flex centring, so the extra height is absorbed by the row. */
.wordmark {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding-block: 5px;
}
