/* Covellum · covellum.com
   Design system and page styles.
   Tokens follow the brand sheet exactly; see CLAUDE.md for usage rules. */

/* ---------------------------------------------------------------- tokens */

:root {
  /* core */
  --ground: #f2f2f3;
  --surface: #e9e9ea;
  --ink: #1d1f20;
  --steel: #5980a6;
  /* Brand accent. It is the colour of the mark's middle bar, and therefore of
     the eyebrow icon and the launch-stack middle bar, which both echo the mark.
     Steel remains the INTERFACE colour (links, focus, footer, dark bands).
     Never use accent for body text: 3.92:1 on ground fails WCAG AA. */
  --accent: #b4633a;

  /* steel ramp */
  --steel-100: #eef6ff;
  --steel-200: #d6ebff;
  --steel-300: #b5d9fd;
  --steel-400: #94bce3;
  --steel-500: #749dc4;
  --steel-600: #597ea3;
  --steel-700: #416180;
  --steel-800: #2c455d;
  --steel-900: #1d2d3d;

  /* neutral ramp */
  --n-100: #f5f5f8;
  --n-200: #e7e7ea;
  --n-300: #d4d4d7;
  --n-400: #b7b7ba;
  --n-500: #98989b;
  --n-600: #7a7a7d;
  --n-700: #5d5d60;
  --n-800: #424244;
  --n-900: #2b2b2d;

  /* semantic */
  --ok: #2f6b46;
  --err: #b3423a;

  /* type */
  --font-display: "Archivo", system-ui, sans-serif;
  --font-body: "IBM Plex Sans", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", monospace;

  --container: 1180px;
  --radius: 2px;
}

/* ---------------------------------------------------------------- base */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img,
svg {
  display: block;
  max-width: 100%;
}

h1,
h2,
h3 {
  font-family: var(--font-display);
  line-height: 1.12;
  letter-spacing: -0.015em;
  margin: 0 0 0.5em;
  text-wrap: balance;
}

h1 {
  font-size: clamp(2.5rem, 5.4vw, 4.1rem);
  font-weight: 700;
}

h2 {
  font-size: clamp(1.7rem, 3vw, 2.4rem);
  font-weight: 700;
}

h3 {
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: -0.008em;
}

p {
  margin: 0 0 1em;
  max-width: 62ch;
}

a {
  color: var(--steel-700);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

a:hover {
  color: var(--steel-800);
}

::selection {
  background: var(--steel-200);
  color: var(--ink);
}

:focus-visible {
  outline: 2px solid var(--steel-500);
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  inset-inline-start: 12px;
  top: -48px;
  z-index: 60;
  background: var(--ink);
  color: var(--ground);
  padding: 10px 16px;
  border-radius: var(--radius);
  text-decoration: none;
  transition: top 0.15s ease;
}

.skip-link:focus {
  top: 12px;
  color: var(--ground);
}

/* ---------------------------------------------------------------- layout */

.container {
  width: min(var(--container), 100% - 48px);
  margin-inline: auto;
}

/* Was clamp(64px, 9vw, 118px), which put 236px between any two sections. The
   sections here are mostly short, so that read as dead space rather than
   rhythm; this keeps the airiness at roughly three quarters of the scale. */
.section {
  padding-block: clamp(52px, 6.5vw, 88px);
}

.section.rule-top {
  border-top: 1px solid var(--n-300);
}

.section-head {
  margin-bottom: clamp(28px, 3.5vw, 44px);
}

.lede {
  font-size: clamp(1.05rem, 1.6vw, 1.25rem);
  color: var(--n-800);
  max-width: 56ch;
}

/* eyebrow: mono label with the miniature strata mark */

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--steel-700);
  margin-bottom: 18px;
}

.eyebrow::before {
  content: "";
  width: 14px;
  height: 13px;
  flex: none;
  background-image:
    linear-gradient(var(--ink), var(--ink)),
    linear-gradient(var(--accent), var(--accent)),
    linear-gradient(var(--ink), var(--ink));
  background-size: 14px 3px, 10px 3px, 8px 3px;
  background-position: 0 0, 3px 5px, 0 10px;
  background-repeat: no-repeat;
}

/* ---------------------------------------------------------------- header */

.site-head {
  border-bottom: 1px solid var(--n-300);
  background: var(--ground);
  position: relative;
  z-index: 50;
}

.head-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  min-height: 76px;
}

.brand {
  display: inline-flex;
  flex: none;
}

.brand img {
  height: 30px;
  width: auto;
}

.site-menu {
  display: flex;
  align-items: center;
  gap: 32px;
}

.site-menu ul {
  display: flex;
  align-items: center;
  gap: 28px;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Scoped to the nav list only. A bare `.site-menu a` also matched the
   language switch and the primary button in .menu-extra, and out-specified
   their own colour rules: the button rendered ink-on-ink and its label
   disappeared. */
.site-menu ul a {
  text-decoration: none;
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 0.95rem;
}

.site-menu ul a:hover {
  color: var(--steel-700);
}

.site-menu ul a[aria-current="page"] {
  color: var(--steel-700);
  box-shadow: 0 2px 0 0 var(--steel-500);
}

.menu-extra {
  display: flex;
  align-items: center;
  gap: 20px;
}

/* Display face, not mono: this matched the nav links before the nav rule was
   scoped, and mono has no Arabic coverage so العربية fell back badly. */
.lang-switch {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 0.95rem;
  color: var(--n-700);
  text-decoration: none;
  border: 1px solid var(--n-300);
  border-radius: var(--radius);
  padding: 7px 12px;
}

.lang-switch:hover {
  color: var(--steel-700);
  border-color: var(--steel-400);
}

/* Padding is uneven because the three bars are 20x16; this brings the button to
   a 44x44 touch target, which is the only size it is ever shown at. */
.nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--n-300);
  border-radius: var(--radius);
  padding: 13px 11px;
  cursor: pointer;
}

.nav-toggle span {
  display: block;
  width: 20px;
  height: 2px;
  background: var(--ink);
}

.nav-toggle span + span {
  margin-top: 5px;
}

/* ---------------------------------------------------------------- buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.95rem;
  padding: 14px 24px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.btn-primary {
  background: var(--ink);
  color: var(--ground);
}

.btn-primary:hover {
  background: var(--steel-800);
  color: var(--ground);
}

.btn-ghost {
  border-color: var(--n-400);
  color: var(--ink);
}

.btn-ghost:hover {
  border-color: var(--steel-500);
  color: var(--steel-700);
  background: var(--steel-100);
}

.btn-small {
  padding: 9px 16px;
  font-size: 0.88rem;
}

.on-dark .btn-primary {
  background: var(--ground);
  color: var(--ink);
}

.on-dark .btn-primary:hover {
  background: var(--steel-200);
  color: var(--steel-900);
}

/* ---------------------------------------------------------------- hero */

.hero {
  padding-block: clamp(72px, 10vw, 132px);
}

.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: clamp(40px, 6vw, 96px);
  align-items: center;
}

.hero .lede {
  margin-top: 20px;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 34px;
}

/* the strata stack: the signature element, derived from the mark */

.strata-wrap {
  min-width: 0;
}

.strata-caption {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--n-600);
  margin-bottom: 14px;
}

.strata {
  display: grid;
  gap: 9px;
}

.strata a {
  display: flex;
  align-items: center;
  min-height: 52px;
  padding-inline: 18px;
  border-radius: var(--radius);
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.04em;
  color: var(--ground);
  text-decoration: none;
  transition: translate 0.18s ease, filter 0.18s ease;
}

.strata a:hover {
  translate: 8px 0;
  filter: brightness(1.18);
  color: var(--ground);
}

.strata a:nth-child(1) { width: 100%; background: var(--ink); }
.strata a:nth-child(2) { width: 80%; margin-inline-start: 8%; background: var(--accent); }
.strata a:nth-child(3) { width: 91%; background: var(--ink); }
.strata a:nth-child(4) { width: 68%; margin-inline-start: 12%; background: var(--steel); }
.strata a:nth-child(5) { width: 52%; background: var(--ink); }

.strata-note {
  font-size: 0.85rem;
  color: var(--n-600);
  margin-top: 14px;
}

@media (prefers-reduced-motion: no-preference) {
  .strata a {
    opacity: 0;
    translate: 0 10px;
    animation: strata-in 0.5s ease forwards;
  }

  .strata a:nth-child(1) { animation-delay: 0.05s; }
  .strata a:nth-child(2) { animation-delay: 0.13s; }
  .strata a:nth-child(3) { animation-delay: 0.21s; }
  .strata a:nth-child(4) { animation-delay: 0.29s; }
  .strata a:nth-child(5) { animation-delay: 0.37s; }

  .strata a:hover {
    translate: 8px 0;
  }

  @keyframes strata-in {
    to {
      opacity: 1;
      translate: 0 0;
    }
  }
}

/* ---------------------------------------------------------------- pillars */

.pillars {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 24px;
}

.pillars.cols-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

/* project cards carrying a preview image: the image sits flush to the card
   edges, so the padding moves onto the body instead of the card */
.pillar.has-thumb {
  padding: 0;
  overflow: hidden;
}

.pillar-thumb {
  display: block;
  width: 100%;
  /* height:auto is required: the width/height attributes act as presentational
     hints, which would make the height definite and stop aspect-ratio applying */
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-bottom: 1px solid var(--n-300);
  background: var(--n-200);
}

.pillar-body {
  padding: clamp(24px, 3vw, 32px);
  display: flex;
  flex-direction: column;
  flex: 1;
}

.pillar {
  background: var(--surface);
  border: 1px solid var(--n-300);
  border-radius: var(--radius);
  padding: clamp(26px, 3.4vw, 40px);
  display: flex;
  flex-direction: column;
}

.pillar p {
  color: var(--n-800);
  flex: 1;
}

.pillar-link {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.95rem;
  display: inline-flex;
  align-items: center;
  gap: 9px;
}

/* chevron drawn in CSS rather than a glyph, so it inherits colour and needs no font */
.pillar-link::after {
  content: "";
  width: 6px;
  height: 6px;
  flex: none;
  border-top: 1.5px solid currentColor;
  border-inline-end: 1.5px solid currentColor;
  rotate: 45deg;
  transition: translate 0.28s cubic-bezier(0.2, 0.7, 0.2, 1);
}

[dir="rtl"] .pillar-link::after {
  rotate: -135deg;
}

/* ---------------------------------------------------------------- motion */

/* Specificity note: `.js .reveal` also sets a transition, so these hover
   rules need two classes to win and must re-declare the reveal properties. */
.pillars .pillar,
.pillars .pillar.reveal {
  transition: transform 0.28s cubic-bezier(0.2, 0.7, 0.2, 1), box-shadow 0.28s ease,
    border-color 0.28s ease, opacity 0.55s ease, translate 0.55s ease;
  box-shadow: 0 1px 2px rgba(29, 31, 32, 0.05);
}

.pillars .pillar:hover {
  transform: translateY(-5px);
  border-color: var(--steel-400);
  box-shadow: 0 18px 38px -16px rgba(29, 31, 32, 0.28), 0 2px 6px rgba(29, 31, 32, 0.06);
}

.pillar:hover .pillar-thumb {
  transform: scale(1.06);
}

.pillar-thumb {
  transition: transform 0.6s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.pillar:hover .pillar-link::after {
  translate: 5px 0;
}

[dir="rtl"] .pillar:hover .pillar-link::after {
  translate: -5px 0;
}

.kv-grid .kv {
  position: relative;
}

.kv-grid .kv::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: -2px;
  width: 2px;
  background: var(--steel-600);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.35s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.tone-dark .kv-grid .kv::before {
  background: var(--accent);
}

.kv-grid .kv:hover::before {
  transform: scaleY(1);
}

.btn {
  transition: transform 0.18s ease, box-shadow 0.2s ease, background 0.15s ease,
    color 0.15s ease, border-color 0.15s ease;
}

.btn-primary:hover,
.btn-ghost:hover {
  transform: translateY(-2px);
}

.btn-primary:hover {
  box-shadow: 0 12px 24px -12px rgba(29, 31, 32, 0.55);
}

.layer {
  transition: background 0.22s ease;
}

.layer:hover {
  background: var(--surface);
}

.layer-tag {
  transition: color 0.22s ease;
}

.layer:hover .layer-tag {
  color: var(--steel-700);
}

/* key-value rows: founder-led / fixed quotes / two languages */

.kv-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(24px, 4vw, 48px);
}

.kv {
  border-inline-start: 2px solid var(--steel-300);
  padding-inline-start: 18px;
}

/* ---------------------------------------------------------------- dark band */

/* A full-bleed dark section breaks the page into tonal bands so it does not
   read as one flat field. The eyebrow mark switches to its reversed colours
   here, the same rule the logo already follows on steel-900. */
.tone-dark {
  background: var(--steel-900);
  border-top-color: transparent;
}

.tone-dark h2 {
  color: var(--ground);
}

.tone-dark .eyebrow {
  color: var(--steel-300);
}

.tone-dark .eyebrow::before {
  background-image:
    linear-gradient(var(--ground), var(--ground)),
    linear-gradient(var(--accent), var(--accent)),
    linear-gradient(var(--ground), var(--ground));
}

.tone-dark .kv {
  border-inline-start-color: var(--accent);
}

.tone-dark .kv h3 {
  color: var(--steel-200);
}

.tone-dark .kv p {
  color: var(--steel-300);
}

.kv h3 {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--steel-700);
  margin-bottom: 10px;
}

.kv p {
  color: var(--n-800);
  font-size: 0.97rem;
  margin: 0;
}

/* ---------------------------------------------------------------- process */

.process {
  list-style: none;
  counter-reset: step;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: clamp(24px, 3.4vw, 40px);
}

.process li {
  counter-increment: step;
  border-top: 2px solid var(--n-300);
  padding-top: 18px;
}

.process li::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--steel-600);
  display: block;
  margin-bottom: 10px;
}

.process h3 {
  font-size: 1.05rem;
  margin-bottom: 8px;
}

.process p {
  font-size: 0.93rem;
  color: var(--n-800);
  margin: 0;
}

/* ---------------------------------------------------------------- services */

.layer-list {
  display: grid;
  gap: 0;
}

.layer {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  gap: 24px;
  padding-block: 30px;
  border-top: 1px solid var(--n-300);
}

.layer:last-child {
  border-bottom: 1px solid var(--n-300);
}

.layer-tag {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--steel-700);
  padding-top: 5px;
}

.layer h3 {
  margin-bottom: 8px;
}

.layer p {
  color: var(--n-800);
  margin: 0;
}

/* ---------------------------------------------------------------- work */

.case {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  gap: clamp(24px, 4vw, 56px);
  padding-block: clamp(40px, 6vw, 64px);
  border-top: 1px solid var(--n-300);
}

.case-meta {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--n-600);
  line-height: 2.1;
  /* Uppercase mono with letterspacing overruns the card by a few pixels on some
     of these strings; balance stops the overflow landing as a one-word orphan. */
  text-wrap: balance;
}

/* Always block, at every width. An earlier mobile override flipped this to
   inline, and because the card markup ran </strong> straight into the text that
   follows, "IN-HOUSE PRODUCT" and "WINDOWS" rendered fused into one word. */
.case-meta strong {
  color: var(--steel-700);
  font-weight: 500;
  display: block;
  margin-bottom: 1px;
}

.case h2 {
  margin-bottom: 14px;
}

.case p {
  color: var(--n-800);
}

.case .pull {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.3rem;
  letter-spacing: -0.01em;
  color: var(--steel-800);
  border-inline-start: 3px solid var(--steel-400);
  padding-inline-start: 18px;
  margin-block: 22px;
  max-width: none;
}

/* Case imagery: a figure slots in as a direct child of .case, between the
   meta column and the text block, both pinned to the wide column. */
.case > figure,
.case > div:last-child {
  grid-column: 2;
}

.case > figure {
  margin: 0 0 6px;
}

.case > figure img,
.case > figure video {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--n-300);
}

/* 16:9 matches the recording; the poster is cropped to the same ratio.
   Reserving the box stops the layout jumping before the poster loads. */
.case > figure video {
  aspect-ratio: 16 / 9;
  background: var(--surface);
}

/* Half-width media. Capped on the figure so the caption tracks the video. */
.case > figure.media-half {
  max-width: 50%;
}

/* Live site preview: the page renders at a real desktop width and is scaled
   down by main.js, so the desktop layout shows rather than the mobile one.
   The box is shorter than the frame, so everything below the crop point is
   clipped. pointer-events is off deliberately: without it a visitor could
   scroll inside the frame and reach the clipped section. */
.embed-frame {
  --frame-w: 1440;
  --frame-h: 900;
  --frame-scale: 0.82;
  position: relative;
  overflow: hidden;
  height: calc(var(--frame-h) * var(--frame-scale) * 1px);
  border: 1px solid var(--n-300);
  background: var(--surface);
}

/* Width and height are set here, not only in JS: the iframe must render at a
   real desktop viewport even if the script never runs, or the embedded page
   falls back to its mobile layout. JS then refines the scale to fit exactly. */
.embed-frame iframe {
  position: absolute;
  top: 0;
  inset-inline-start: 0;
  width: calc(var(--frame-w) * 1px);
  height: calc(var(--frame-h) * 1px);
  border: 0;
  transform: scale(var(--frame-scale));
  transform-origin: top left;
  pointer-events: none;
}

/* Wide media spans the meta column too, then backs off 25% so it does not
   dominate the case. Both the preview frame and the catalogue video use it,
   so they render at matching widths. */
.case > figure.media-wide {
  grid-column: 1 / -1;
  max-width: 75%;
}

[dir="rtl"] .embed-frame iframe {
  transform-origin: top right;
}

.case > figure figcaption,
.flagship-media figcaption,
.shots figcaption {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--n-600);
  margin-top: 10px;
}

/* ---------------------------------------------------------------- about */

.principles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(24px, 4vw, 44px) clamp(24px, 5vw, 72px);
}

.prose p {
  color: var(--n-800);
}

/* flagship: the studio's own product, given more room than a portfolio card */
.flagship {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(28px, 4vw, 60px);
  align-items: center;
}

.flagship-media {
  margin: 0;
  width: 100%;
}

/* Standalone product-page shots back off 25%, the same restraint .media-wide
   applies on Projects. Two reasons: at full container width the screenshot
   dominates the page, and a 1180px box asks more of the capture than it has —
   at 885px the same file lands at roughly 2.2x device pixels and stays sharp.
   Scoped to direct children of .container so the homepage .flagship block,
   which is already only half the row, keeps its full width. */
.container > .flagship-media {
  max-width: 75%;
}

.flagship-media img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border: 1px solid var(--n-300);
  border-radius: var(--radius);
}

.flagship h2 {
  margin-bottom: 14px;
}

/* Two portrait captures side by side. Capped well short of the container:
   at full width a 840x1319 image would tower over the surrounding copy. */
.shots {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(20px, 3vw, 44px);
  align-items: start;
  max-width: 720px;
}

.shots figure {
  margin: 0;
}

.shots img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--n-300);
  border-radius: var(--radius);
}

/* The Arabic capture sits inside the dark band as evidence for the claim
   printed directly above it, so its caption has to reverse too. */
.tone-dark .flagship-media {
  margin-top: clamp(32px, 5vw, 52px);
}

.tone-dark .flagship-media figcaption {
  color: var(--steel-300);
}

.flagship .btn {
  margin-top: 22px;
}

/* Status for a product that has not shipped yet. Deliberately NOT a badge:
   it reuses the border-inline-start rule that .kv and .pull already use, so it
   reads as native to the studio rather than as a bolted-on UI chip. The accent
   carries the signal as a rule; the label stays steel-700, which clears WCAG AA
   on ground at 5.78:1 where terracotta text would fail at 3.92:1. */
.status {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.76rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--steel-700);
  border-inline-start: 3px solid var(--accent);
  padding-inline-start: 14px;
  padding-block: 3px;
}

/* founder: portrait beside a pull quote */
.founder {
  display: grid;
  grid-template-columns: minmax(0, 290px) minmax(0, 1fr);
  gap: clamp(24px, 4vw, 56px);
  align-items: center;
  margin-bottom: clamp(28px, 4vw, 44px);
}

.founder-photo {
  margin: 0;
}

.founder-photo img {
  display: block;
  width: 100%;
  height: auto;
}

.founder-quote {
  margin: 0;
}

.founder-quote p {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.1rem, 1.9vw, 1.45rem);
  line-height: 1.4;
  letter-spacing: -0.01em;
  color: var(--steel-800);
  border-inline-start: 3px solid var(--steel-400);
  padding-inline-start: 20px;
  margin: 0;
  max-width: none;
}

.founder-quote cite {
  display: block;
  margin-top: 16px;
  padding-inline-start: 23px;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-style: normal;
  color: var(--n-600);
}

.prose .lead-ink {
  color: var(--ink);
}

/* ---------------------------------------------------------------- contact */

.contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
  gap: clamp(40px, 6vw, 88px);
  align-items: start;
}

.enquiry {
  display: grid;
  gap: 22px;
}

/* Direct children only. A bare `.field label` (0,1,1) also matched the checkbox
   labels inside `.field.checks > .checks-grid` and out-specified `.check`
   (0,1,0), so those labels silently rendered as blocks with an 8px bottom
   margin instead of the intended flex row, and no padding rule could reach
   them. Same failure mode as the `.site-menu a` bug. */
.field > label,
.field > legend {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.74rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--n-700);
  margin-bottom: 8px;
  padding: 0;
}

.field input[type="text"],
.field input[type="email"],
.field input[type="tel"],
.field select,
.field textarea {
  width: 100%;
  background: #ffffff;
  border: 1px solid var(--n-400);
  border-radius: var(--radius);
  padding: 12px 14px;
  font: inherit;
  font-size: 1rem;
  color: var(--ink);
}

.field textarea {
  resize: vertical;
  min-height: 150px;
}

.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: none;
  border-color: var(--steel-600);
  box-shadow: 0 0 0 3px var(--steel-200);
}

.field-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 22px;
}

.checks {
  border: 0;
  margin: 0;
  padding: 0;
}

.checks-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 24px;
}

.check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 0.95rem;
}

.check input {
  accent-color: var(--steel-600);
  width: 17px;
  height: 17px;
  margin-top: 2px;
  flex: none;
}

.form-note {
  font-size: 0.85rem;
  color: var(--n-600);
  margin: 0;
}

.form-status {
  font-size: 0.95rem;
  margin: 0;
  min-height: 1.4em;
}

.form-status[data-state="ok"] {
  color: var(--ok);
}

.form-status[data-state="err"] {
  color: var(--err);
}

/* Launch-list capture. Separate from .enquiry because it has to stay compact
   enough to sit inside a prose column: one field and the button on one row. */
.notify {
  display: grid;
  gap: 14px;
  margin-top: 30px;
  max-width: 520px;
}

.notify-row {
  /* Both controls take this height explicitly. Left to their own padding they
     disagree by ~10px, because the button's box is sized by the display face's
     normal line-height and the input's by its own padding. */
  --control-h: 52px;
  display: flex;
  gap: 12px;
  align-items: flex-end;
}

.notify-row .field {
  flex: 1 1 auto;
  min-width: 0;
}

.notify-row .field input {
  height: var(--control-h);
}

.notify-row .btn {
  flex: none;
  height: var(--control-h);
  padding-block: 0;
}

.honey {
  position: absolute;
  inset-inline-start: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.direct {
  background: var(--surface);
  border: 1px solid var(--n-300);
  border-radius: var(--radius);
  padding: clamp(26px, 3vw, 36px);
}

.direct h2 {
  font-size: 1.2rem;
}

.direct-line {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.05rem;
  margin-bottom: 10px;
  overflow-wrap: anywhere;
}

.direct .fine {
  font-size: 0.88rem;
  color: var(--n-700);
  margin: 18px 0 0;
}

/* ---------------------------------------------------------------- cta band */

.cta-band {
  padding-block: clamp(44px, 5vw, 68px);
  background: var(--steel-900);
  color: var(--ground);
}

.cta-band h2 {
  color: var(--ground);
}

.cta-band p {
  color: var(--steel-300);
}

.cta-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 28px;
}

/* Keep the copy and the button on one row. Without a zero flex-basis the text
   block claims its full content width and bumps the button onto a new line as
   soon as the heading runs long. */
.cta-inner > div {
  flex: 1 1 0;
  min-width: 0;
}

.cta-inner > .btn {
  flex: 0 0 auto;
}

/* ---------------------------------------------------------------- footer */

.site-foot {
  background: var(--steel-900);
  color: var(--steel-300);
  padding-block: clamp(48px, 6vw, 72px) 32px;
}

.foot-top {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, 1fr));
  gap: clamp(28px, 4vw, 48px);
  padding-bottom: 40px;
}

.site-foot .brand img {
  height: 26px;
}

.foot-line {
  margin-top: 18px;
  font-size: 0.92rem;
  color: var(--steel-300);
  max-width: 44ch;
}

.foot-col h3 {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--steel-500);
  margin-bottom: 14px;
}

.foot-col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 9px;
}

.foot-col a {
  color: var(--steel-300);
  text-decoration: none;
  font-size: 0.95rem;
  overflow-wrap: anywhere;
}

.foot-col a:hover {
  color: var(--ground);
}

.foot-col p {
  color: var(--steel-300);
  font-size: 0.95rem;
  margin: 0 0 9px;
}

.foot-bottom {
  border-top: 1px solid rgba(242, 242, 243, 0.16);
  padding-top: 22px;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 12px;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--steel-500);
}

/* Statutory company details: full-width fine print under the copyright row.
   max-width must be none: the global p rule (62ch) would otherwise clamp the
   flex basis and keep this on the copyright row instead of its own. */
.foot-legal {
  flex-basis: 100%;
  max-width: none;
  margin: 2px 0 0;
  line-height: 1.8;
}

/* ---------------------------------------------------------------- reveal */

.reveal {
  opacity: 1;
}

@media (prefers-reduced-motion: no-preference) {
  .js .reveal {
    opacity: 0;
    translate: 0 14px;
    transition: opacity 0.55s ease, translate 0.55s ease;
  }

  .js .reveal.in {
    opacity: 1;
    translate: 0 0;
  }
}

.ltr {
  direction: ltr;
  unicode-bidi: isolate;
  display: inline-block;
}

/* ---------------------------------------------------------------- rtl */

[dir="rtl"] {
  --font-display: "IBM Plex Sans Arabic", "Archivo", system-ui, sans-serif;
  --font-body: "IBM Plex Sans Arabic", "IBM Plex Sans", system-ui, sans-serif;
}

[dir="rtl"] body,
body[dir="rtl"] {
  line-height: 1.8;
}

[dir="rtl"] h1,
[dir="rtl"] h2,
[dir="rtl"] h3 {
  letter-spacing: 0;
  line-height: 1.3;
}

[dir="rtl"] h1 {
  font-size: clamp(2.1rem, 4.6vw, 3.4rem);
}

[dir="rtl"] .eyebrow,
[dir="rtl"] .status,
[dir="rtl"] .strata-caption,
[dir="rtl"] .kv h3,
[dir="rtl"] .layer-tag,
[dir="rtl"] .case-meta,
[dir="rtl"] .founder-quote cite,
[dir="rtl"] .case > figure figcaption,
[dir="rtl"] .flagship-media figcaption,
[dir="rtl"] .shots figcaption,
[dir="rtl"] .field > label,
[dir="rtl"] .field > legend,
[dir="rtl"] .check,
[dir="rtl"] .foot-col h3 {
  font-family: var(--font-body);
  letter-spacing: 0;
  font-weight: 500;
}

[dir="rtl"] .foot-bottom {
  font-family: var(--font-body);
}

[dir="rtl"] .strata a {
  font-family: var(--font-body);
  letter-spacing: 0;
  font-size: 0.9rem;
}

[dir="rtl"] .strata a:hover {
  translate: -8px 0;
}

[dir="rtl"] .eyebrow::before {
  background-position: 100% 0, calc(100% - 3px) 5px, 100% 10px;
}

/* ---------------------------------------------------------------- media */

@media (max-width: 980px) {
  .nav-toggle {
    display: block;
  }

  .site-menu {
    display: none;
    position: absolute;
    top: 100%;
    inset-inline: 0;
    background: var(--ground);
    border-bottom: 1px solid var(--n-300);
    padding: 20px 24px 28px;
  }

  .site-menu.open {
    display: block;
  }

  .site-menu ul {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
  }

  /* touch targets: bare links sat at ~20px against a 44px guideline. Padding
     grows the hit area without changing how the text looks. */
  .site-menu ul a {
    display: inline-block;
    padding-block: 12px;
  }

  .foot-col a,
  .direct-line {
    display: inline-block;
    padding-block: 7px;
  }

  .foot-col ul {
    gap: 2px;
  }

  .menu-extra {
    margin-top: 22px;
    padding-top: 20px;
    border-top: 1px solid var(--n-300);
  }

  .hero-grid,
  .contact-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .pillars,
  .pillars.cols-3,
  .principles,
  .checks-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .founder {
    grid-template-columns: minmax(0, 1fr);
    justify-items: start;
  }

  /* Not grouped with .founder: the portrait wants start alignment inside its
     260px cap, but the flagship image is a 16:9 card that must span the column.
     justify-items: start would size the figure to fit-content, and a percentage
     width on the image inside it has nothing to resolve against, so it collapses. */
  .flagship {
    grid-template-columns: minmax(0, 1fr);
  }

  .founder-photo {
    max-width: 260px;
  }

  .shots {
    grid-template-columns: minmax(0, 1fr);
    max-width: 320px;
  }

  .kv-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 28px;
  }

  .process {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .layer,
  .case {
    grid-template-columns: minmax(0, 1fr);
    gap: 10px;
  }

  .case-meta {
    line-height: 1.8;
  }

  .case > figure,
  .case > div:last-child {
    grid-column: auto;
  }

  /* Width caps are a desktop refinement; below this they would be unwatchable.
     A 75% cap on a 327px column leaves 245px, which is not enough to read a
     screenshot of a desktop widget. */
  .case > figure.media-half,
  .case > figure.media-wide,
  .container > .flagship-media {
    max-width: none;
  }

  .embed-frame {
    --frame-scale: 0.62;
  }
}

@media (max-width: 760px) {
  .embed-frame {
    --frame-scale: 0.44;
  }
}

@media (max-width: 560px) {
  .embed-frame {
    --frame-scale: 0.28;
  }
}

@media (max-width: 560px) {
  .process {
    grid-template-columns: minmax(0, 1fr);
  }

  .field-row {
    grid-template-columns: minmax(0, 1fr);
  }

  /* The label is the tap target, since the checkbox sits inside it. At its
     natural height that is 25px, only just clear of the 24px AA floor, so on
     touch it gets padded out to a comfortable 43px. */
  .check {
    padding-block: 9px;
  }

  .notify-row {
    flex-direction: column;
    align-items: stretch;
  }

  .foot-top {
    grid-template-columns: minmax(0, 1fr);
    gap: 30px;
  }

  .cta-inner {
    flex-direction: column;
    align-items: flex-start;
  }

  /* Column direction: flex-basis would apply to height, so hand sizing back. */
  .cta-inner > div {
    flex: 0 1 auto;
  }
}
