/* ============================================================
   Shlomi Aflalo — personal brand site
   Dependency-free design system. Two colours only: black and white.
   Every value below is a tint of one of them — zero chroma anywhere.
   Fonts self-hosted: Space Grotesk (display), JetBrains Mono.
   ============================================================ */

@font-face {
  font-family: "Space Grotesk";
  src: url("/assets/fonts/space-grotesk-latin-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Space Grotesk";
  src: url("/assets/fonts/space-grotesk-latin-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  /* Metric-matched stand-in so the swap to IBM Plex Sans does not reflow text.
     size-adjust measured in-browser against Arial: 100.4%. */
  font-family: "Plex Fallback";
  src: local("Arial"), local("Helvetica"), local("Liberation Sans");
  size-adjust: 100.4%;
  ascent-override: 102.5%;
  descent-override: 27.5%;
  line-gap-override: 0%;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Sans";
  src: url("/assets/fonts/ibm-plex-sans-latin-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("/assets/fonts/ibm-plex-sans-latin-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("/assets/fonts/ibm-plex-sans-latin-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("/assets/fonts/jetbrains-mono-latin-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("/assets/fonts/jetbrains-mono-latin-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: dark;
  --bg: #080808;
  --bg-raise: #0e0e0e;
  --panel: #121212;
  --panel-edge: #272727;
  --text: #d2d2d2;
  --text-strong: #fafafa;
  --muted: #a4a4a4;
  /* the accent is white — so a primary button inverts instead of colouring */
  --accent: #ffffff;
  --accent-ink: #080808;      /* what sits on top of an accent fill */
  --accent-2: #cfcfcf;        /* the far end of the one gradient we allow */
  --accent-soft: rgba(255, 255, 255, 0.085);
  --accent-edge: rgba(255, 255, 255, 0.24);
  /* kept as names so component rules need no rewrite — both are now white */
  --green: #ffffff;
  --green-soft: rgba(255, 255, 255, 0.07);
  --display: "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --mono: "JetBrains Mono", "SF Mono", SFMono-Regular, ui-monospace, "Cascadia Mono", Menlo, Consolas, monospace;
  --sans: "IBM Plex Sans", "Plex Fallback", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --radius: 14px;
  --maxw: 1180px;

  /* motion tokens — physical, not ease-in-out on everything */
  --dur-micro: 120ms;
  --dur-base: 240ms;
  --dur-narrative: 520ms;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);

  /* elevation — multi-layer, never a single flat drop */
  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.3), 0 2px 6px rgba(0, 0, 0, 0.22);
  --shadow-2: 0 2px 4px rgba(0, 0, 0, 0.32), 0 8px 20px rgba(0, 0, 0, 0.34);
  --shadow-3: 0 4px 8px rgba(0, 0, 0, 0.34), 0 18px 44px rgba(0, 0, 0, 0.46);
  --shadow-lift: 0 6px 12px rgba(0, 0, 0, 0.34), 0 26px 60px rgba(0, 0, 0, 0.52);
}

/* Perceptual lightness where the browser supports it. Chroma is 0 on every
   step, so the ramp is a true neutral — no blue or warm cast creeping in. */
@supports (color: oklch(0.5 0.1 60)) {
  :root {
    --bg: oklch(0.145 0 0);
    --bg-raise: oklch(0.183 0 0);
    --panel: oklch(0.213 0 0);
    --panel-edge: oklch(0.303 0 0);
    --text: oklch(0.868 0 0);
    --text-strong: oklch(0.977 0 0);
    --muted: oklch(0.72 0 0);
    --accent: oklch(1 0 0);
  }
}

* { margin: 0; padding: 0; box-sizing: border-box; }

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  background:
    radial-gradient(58vw 58vw at 88% -8%, rgba(255, 255, 255, 0.055), transparent 62%),
    radial-gradient(50vw 50vw at -12% 34%, rgba(255, 255, 255, 0.028), transparent 60%),
    radial-gradient(46vw 46vw at 108% 78%, rgba(255, 255, 255, 0.035), transparent 60%),
    var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, .stat b {
  font-family: var(--display);
}

::selection { background: var(--accent); color: var(--accent-ink); }

/* keyboard focus: one visible ring everywhere, never for mouse users */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
  padding: 12px 20px;
  border-radius: 0 0 12px 0;
}
.skip-link:focus { left: 0; text-decoration: none; }
main[tabindex="-1"]:focus { outline: none; }

img { max-width: 100%; display: block; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Scoped to running text only: nav, cards and buttons keep the clean
   undecorated treatment because they are already unambiguous affordances. */
.prose p a:not(.btn), .prose li a:not(.btn) {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: rgba(255, 255, 255, 0.45);
}
.prose p a:not(.btn):hover, .prose li a:not(.btn):hover { text-decoration-color: #fff; }

/* One container width for every section including the hero. Widening only the
   hero pushed its two columns to opposite edges and opened a void between
   them; a single width keeps the headline and the phone reading as one pair,
   and every section aligns on the same edge with no step anywhere. */
.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 24px; }

/* ---------- floating round menu (no top bar) ---------- */

.floating-menu {
  position: fixed;
  top: 18px;
  right: 18px;
  z-index: 60;
}

.nav-toggle {
  width: 54px;
  height: 54px;
  border-radius: 50%;
  background: rgba(14, 14, 14, 0.82);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--panel-edge);
  color: var(--text-strong);
  font-size: 21px;
  line-height: 1;
  cursor: pointer;
  display: grid;
  place-items: center;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.nav-toggle:hover { border-color: var(--accent-edge); transform: scale(1.06); }

.nav {
  position: absolute;
  top: 66px;
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  min-width: 236px;
  background: rgba(14, 14, 14, 0.97);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--panel-edge);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(-8px);
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0s linear 0.18s;
}
.nav-open .nav {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateY(0);
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.nav a {
  color: var(--text);
  font-size: 15px;
  font-weight: 500;
  padding: 13px 20px;
  border-bottom: 1px solid rgba(39, 39, 39, 0.55);
}
.nav a:hover { color: var(--accent); background: rgba(255, 255, 255, 0.06); text-decoration: none; }
.nav a.active { color: var(--text-strong); }
.nav a:last-child { border-bottom: none; }

.lang-switch {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--muted) !important;
}
.lang-switch:hover { color: var(--accent) !important; }

@media (prefers-reduced-motion: reduce) {
  .nav, .nav-open .nav { transition: none; }
}

/* ---------- hero ---------- */

.hero { padding: 84px 0 64px; position: relative; overflow: hidden; }
.hero::before {
  content: "";
  position: absolute;
  top: -180px; right: -120px;
  width: 520px; height: 520px;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.09), transparent 65%);
  pointer-events: none;
  z-index: 1;
  animation: glow-drift 16s ease-in-out infinite alternate;
}
@keyframes glow-drift {
  from { transform: translate(0, 0) scale(1); }
  to   { transform: translate(-90px, 60px) scale(1.2); }
}
@media (prefers-reduced-motion: reduce) {
  .hero::before { animation: none; }
}

/* cinematic hero: figure-free Borobudur stupa backdrop under the dark gradient
   (assets/borobudur-stupas.jpg contains no person, so text can never sit on a face)
   Desaturated: on a two-colour site the only thing allowed to carry colour is
   the client work itself. */
.hero.hero-cinema {
  background:
    linear-gradient(180deg, rgba(8, 8, 8, 0.93) 0%, rgba(8, 8, 8, 0.80) 45%, rgba(8, 8, 8, 0.97) 100%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0.03)),
    url("/assets/borobudur-stupas.jpg") center 32% / cover no-repeat;
  border-bottom: 1px solid var(--panel-edge);
}
.hero .wrap { position: relative; z-index: 2; }


/* hero layout with photo */
.hero-grid {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 48px;
  align-items: center;
}
.hero-photo {
  width: 290px;
  height: 390px;
  object-fit: cover;
  object-position: 50% 18%;
  border-radius: 22px;
  border: 1px solid var(--panel-edge);
  box-shadow: var(--shadow-lift);
}
@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; gap: 30px; }
  .hero-photo { width: 210px; height: 270px; }
}

.eyebrow {
  font-family: var(--mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 18px;
}

.hero h1 {
  font-size: clamp(38px, 6.4vw, 88px);
  line-height: 1.02;
  letter-spacing: -0.034em;
  color: var(--text-strong);
  max-width: 15ch;      /* measured in characters, so it breaks the same at every size */
}
/* Emphasis without a second colour. The setup clause sits back in silver and
   the payoff comes forward in pure white — the reverse of the old amber
   gradient, which faded the very word that has to land. */
.hero h1 { color: #a6a6a6; }
.hero h1 .hl { color: #ffffff; }

/* faint blueprint grid over the hero */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px);
  background-size: 46px 46px;
  -webkit-mask-image: radial-gradient(75% 65% at 30% 22%, #000, transparent 85%);
  mask-image: radial-gradient(75% 65% at 30% 22%, #000, transparent 85%);
}

.hero .sub {
  margin-top: 22px;
  font-size: clamp(17px, 2vw, 20px);
  color: var(--muted);
  max-width: 700px;
}

.cta-row { margin-top: 34px; display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }

.btn {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  border-radius: 10px;
  padding: 13px 22px;
  font-size: 16px;
  font-weight: 600;
  transition: transform var(--dur-micro) var(--ease-out), box-shadow var(--dur-micro) var(--ease-out);
  cursor: pointer;
  border: none;
}
.btn:hover { text-decoration: none; transform: translateY(-1px); }

.btn-primary {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: var(--accent-ink);
  box-shadow: 0 6px 22px rgba(255, 255, 255, 0.25);
}
.btn-primary:hover { box-shadow: 0 8px 28px rgba(255, 255, 255, 0.35); }

.btn-whatsapp {
  background: var(--green-soft);
  color: var(--green);
  border: 1px solid rgba(255, 255, 255, 0.4);
}
.btn-whatsapp:hover { background: rgba(255, 255, 255, 0.2); }

.btn-ghost {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--panel-edge);
}
.btn-ghost:hover { border-color: var(--accent-edge); color: var(--accent); }

.hero-note { margin-top: 16px; font-size: 14px; color: var(--muted); }


/* ---------- stat strip ---------- */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
  margin: 30px 0 0;
}
.stat {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--radius);
  padding: 22px 24px;
}
.stat b {
  display: block;
  font-size: 32px;
  letter-spacing: -0.03em;
  line-height: 1.1;
  background: linear-gradient(160deg, #ffffff 10%, #9a9a9a 95%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.stat span { font-size: 13.5px; color: var(--muted); }

/* ---------- sections ---------- */

/* Rhythm is deliberate: a tight proof strip right after the open hero, then
   room again. Uniform padding is what makes a page scroll like a list. */
section.block { padding: clamp(64px, 7vw, 104px) 0; }
section.block.tight { padding: clamp(38px, 4vw, 56px) 0; }
section.block.roomy { padding: clamp(84px, 10vw, 148px) 0; }
section.block.alt { background: var(--bg-raise); border-top: 1px solid var(--panel-edge); border-bottom: 1px solid var(--panel-edge); }

/* full-bleed photo section (Borobudur backdrop, heavily darkened) */
section.block.photo-bg {
  background:
    linear-gradient(180deg, rgba(8, 8, 8, 0.94), rgba(8, 8, 8, 0.82) 45%, rgba(8, 8, 8, 0.95)),
    url("/assets/borobudur-stupas.jpg") center 78% / cover no-repeat;
  border-top: 1px solid var(--panel-edge);
  border-bottom: 1px solid var(--panel-edge);
}
.photo-bg .card,
.photo-bg .price-card {
  background: rgba(18, 18, 18, 0.82);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.photo-bg .browser { background: rgba(18, 18, 18, 0.9); }

/* warm glow section (contact) */
section.block.glow-bg {
  background:
    radial-gradient(56% 70% at 50% 0%, rgba(255, 255, 255, 0.09), transparent 70%),
    var(--bg-raise);
}

.section-head { max-width: 640px; margin-bottom: 42px; }
.section-head h2 {
  font-size: clamp(28px, 3.8vw, 42px);
  letter-spacing: -0.025em;
  color: var(--text-strong);
  line-height: 1.12;
}
.section-head p { margin-top: 12px; color: var(--muted); }

/* ---------- cards ---------- */

.grid { display: grid; gap: 18px; }
.grid.cols-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid.cols-4 { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }

.card {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--radius);
  padding: 30px 30px 28px;
  transition: border-color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
  display: flex;
  flex-direction: column;
}
.card { position: relative; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.045); }
.card > * { position: relative; z-index: 1; }
.card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 0%), rgba(255, 255, 255, 0.11), transparent 62%);
  opacity: 0;
  transition: opacity 0.28s ease;
  pointer-events: none;
  z-index: 0;
}
.card:hover::after { opacity: 1; }
.card:hover {
  border-color: var(--accent-edge);
  transform: translateY(-3px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), var(--shadow-3);
}

.card .icon {
  width: 42px; height: 42px;
  border-radius: 10px;
  background: var(--accent-soft);
  color: var(--accent);
  display: grid; place-items: center;
  margin-bottom: 16px;
}
.card h2, .card h3 { font-size: 19px; color: var(--text-strong); margin-bottom: 8px; }
.card p { font-size: 15px; color: var(--muted); flex: 1; }
.card .more {
  margin-top: 16px;
  font-family: var(--mono);
  font-size: 13px;
}

/* ---------- case study ---------- */

.case {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: 40px;
  align-items: center;
}
@media (max-width: 860px) { .case { grid-template-columns: 1fr; } }

.browser {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
}
.browser .bar {
  display: flex; align-items: center; gap: 8px;
  background: #0e0e0e;
  border-bottom: 1px solid var(--panel-edge);
  padding: 10px 14px;
}
.browser .bar i { width: 10px; height: 10px; border-radius: 50%; display: block; }
.browser .bar i:nth-child(1) { background: rgba(255, 255, 255, 0.55); }
.browser .bar i:nth-child(2) { background: rgba(255, 255, 255, 0.34); }
.browser .bar i:nth-child(3) { background: rgba(255, 255, 255, 0.2); }
.browser .bar .url {
  margin-left: 10px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
  background: var(--bg);
  border-radius: 6px;
  padding: 3px 10px;
}
.browser .shot { width: 100%; height: auto; }

.case-body h3 { font-size: 24px; color: var(--text-strong); }
/* Global, not scoped to .case-body — that wrapper is gone since the portfolio
   rebuild, which left the tag spans with no flex and no gap, running together. */
.tags { display: flex; flex-wrap: wrap; gap: 9px; margin: 14px 0 18px; }
.tag + .tag { margin-left: 0; }
.tag {
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.7;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid var(--accent-edge);
  border-radius: 999px;
  padding: 4px 13px;
  white-space: nowrap;
}
.case-body ul { list-style: none; margin-top: 6px; }
.case-body li { padding-left: 26px; position: relative; margin-bottom: 10px; color: var(--muted); font-size: 15.5px; }
.case-body li::before {
  content: "▸";
  position: absolute; left: 4px;
  color: var(--accent);
}
.case-body li b { color: var(--text); }

/* ---------- process ---------- */

.steps { counter-reset: step; }
.step {
  position: relative;
}
.step::before {
  counter-increment: step;
  content: "0" counter(step);
  font-family: var(--mono);
  font-size: 13px;
  color: var(--accent);
  display: block;
  margin-bottom: 12px;
}

/* ---------- faq ---------- */

.faq details {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--radius);
  margin-bottom: 12px;
  overflow: hidden;
}
.faq summary {
  cursor: pointer;
  padding: 20px 24px;
  font-weight: 600;
  color: var(--text-strong);
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--accent); font-size: 20px; flex-shrink: 0; }
.faq details[open] summary::after { content: "–"; }
.faq .faq-a { padding: 0 24px 22px; color: var(--muted); font-size: 15.5px; }

/* ---------- contact ---------- */

.contact-grid {
  display: grid;
  grid-template-columns: 1fr 1.1fr;
  gap: 40px;
}
@media (max-width: 860px) { .contact-grid { grid-template-columns: 1fr; } }

.contact-side h1, .contact-side h2 { font-size: clamp(26px, 3.4vw, 36px); color: var(--text-strong); letter-spacing: -0.015em; }
.contact-side p { margin-top: 14px; color: var(--muted); }

.contact-channels { margin-top: 26px; display: flex; flex-direction: column; gap: 12px; }
.channel {
  display: flex; align-items: center; gap: 14px;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: 12px;
  padding: 16px 20px;
  color: var(--text);
}
.channel:hover { border-color: var(--accent-edge); text-decoration: none; }
.channel .ch-icon {
  width: 38px; height: 38px; border-radius: 9px;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent);
  flex-shrink: 0;
}
.channel.wa .ch-icon { background: var(--green-soft); color: var(--green); }
.channel b { display: block; font-size: 15px; color: var(--text-strong); }
.channel span { font-size: 13.5px; color: var(--muted); font-family: var(--mono); }

form.contact-form {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--radius);
  padding: 30px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.field label {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 7px;
}
.field input, .field select, .field textarea {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--panel-edge);
  border-radius: 9px;
  color: var(--text-strong);
  font-family: var(--sans);
  font-size: 15.5px;
  padding: 13px 15px;
  transition: border-color 0.15s ease;
}

/* The native select arrow is drawn hard against the right edge and in the OS
   colour, which reads as unfinished on a dark form. Draw our own instead. */
.field select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 44px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%238c8c8c' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
  cursor: pointer;
}
.field select:hover { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%23ffffff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
/* the popup list itself is OS-drawn; keep it readable on both themes */
.field select option { background: var(--bg-raise); color: var(--text-strong); }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--accent); }
.field textarea { resize: vertical; min-height: 120px; }
.form-note { font-size: 13px; color: var(--muted); }
.form-status { font-size: 14.5px; display: block; padding: 0; margin-top: -16px; border-radius: 9px; }
.form-status.ok { margin-top: 0; padding: 12px 14px; background: var(--green-soft); color: var(--green); }
.form-status.err {
  margin-top: 0;
  padding: 12px 14px 12px 16px;
  background: rgba(255, 255, 255, 0.06);
  border-left: 3px solid var(--accent);   /* the error signal, now shape not hue */
  color: var(--text-strong);
  font-weight: 500;
}

/* ---------- footer ---------- */

.site-footer {
  border-top: 1px solid var(--panel-edge);
  background: linear-gradient(180deg, transparent, rgba(14, 14, 14, 0.55));
  padding: 58px 0 26px;
  font-size: 14.5px;
  color: var(--muted);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.7fr 1fr 1fr 1fr;
  gap: 40px;
  padding-bottom: 34px;
}
@media (max-width: 900px) { .footer-grid { grid-template-columns: 1fr 1fr; gap: 34px; } }
@media (max-width: 540px) { .footer-grid { grid-template-columns: 1fr; gap: 30px; } }

.footer-brand { max-width: 340px; }
/* Was an "SA" monogram tile — a stand-in for a brand that does not exist.
   On a personal-brand site the mark is the person. */
.footer-logo {
  width: 38px; height: 38px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
  border: 1px solid var(--panel-edge);
}
.footer-name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 17px;
  color: var(--text-strong);
  margin-top: 13px;
}
.footer-tag { margin-top: 8px; font-size: 14px; line-height: 1.6; }
.footer-status { margin-top: 13px; font-size: 13.5px; }


.footer-col { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.footer-h {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-strong);
  margin-bottom: 3px;
}
.site-footer a { color: var(--muted); }
.site-footer a:hover { color: var(--accent); }

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: space-between;
  align-items: center;
  border-top: 1px solid var(--panel-edge);
  padding-top: 22px;
  font-size: 13.5px;
}
.footer-bottom a { font-family: var(--mono); font-size: 12.5px; }

/* ---------- prose pages (service pages, case study) ---------- */

.prose { max-width: 760px; }
.prose h1 { font-size: clamp(30px, 4.4vw, 44px); line-height: 1.15; letter-spacing: -0.02em; color: var(--text-strong); }
.prose h2 { font-size: 24px; color: var(--text-strong); margin: 40px 0 14px; letter-spacing: -0.01em; }
.prose h3 { font-size: 19px; color: var(--text-strong); margin: 28px 0 10px; }
.prose p { margin: 14px 0; color: var(--text); max-inline-size: 68ch; }
.prose p.lead { font-size: 19px; color: var(--muted); margin-top: 18px; }
.prose ul, .prose ol { margin: 14px 0 14px 24px; }
.prose li { margin-bottom: 8px; }

.prose table {
  width: 100%;
  border-collapse: collapse;
  margin: 22px 0;
  font-size: 14.5px;
}
.prose th, .prose td {
  padding: 11px 13px;
  text-align: left;
  border-bottom: 1px solid var(--panel-edge);
  vertical-align: top;
}
.prose thead th {
  font-family: var(--display);
  font-size: 14px;
  color: var(--text-strong);
  background: rgba(18, 18, 18, 0.75);
  border-bottom-color: var(--accent-edge);
}
.prose td { color: var(--text); }
.prose tbody tr:last-child td { border-bottom: none; }
.prose .cta-row { margin: 34px 0; }

.breadcrumbs {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--muted);
  margin: 28px 0 40px;
}
@media (max-width: 760px) {
  .breadcrumbs { padding-right: 64px; }
}
.breadcrumbs a { color: var(--muted); }
.breadcrumbs a:hover { color: var(--accent); }
.breadcrumbs .sep { margin: 0 8px; color: var(--panel-edge); }

/* headshot */
.headshot {
  width: 168px; height: 168px;
  border-radius: 20px;
  object-fit: cover;
  object-position: 50% 18%;
  border: 1px solid var(--panel-edge);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.4);
}

/* photo figure (about pages) */
.photo-figure { margin: 34px 0; }
.photo-figure img {
  width: 100%;
  border-radius: var(--radius);
  border: 1px solid var(--panel-edge);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.4);
}
.photo-figure figcaption {
  margin-top: 10px;
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--muted);
}

.about-grid {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 36px;
  align-items: start;
}
@media (max-width: 700px) { .about-grid { grid-template-columns: 1fr; } }

/* floating whatsapp */
.wa-float {
  position: fixed;
  right: 22px; bottom: 22px;
  z-index: 60;
  width: 56px; height: 56px;
  border-radius: 50%;
  background: var(--green);
  color: var(--accent-ink);
  display: grid; place-items: center;
  box-shadow: 0 10px 30px rgba(255, 255, 255, 0.35);
  transition: transform 0.15s ease;
}
.wa-float:hover { transform: scale(1.07); text-decoration: none; }

/* ---------- pricing (ID market) ---------- */

.price-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
  gap: 18px;
  align-items: stretch;
}
.price-card {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: var(--radius);
  padding: 32px 30px 30px;
  display: flex;
  flex-direction: column;
}
.price-card.featured {
  border-color: var(--accent-edge);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.06), var(--panel) 40%);
}
.price-badge {
  position: absolute;
  top: -12px; left: 50%;
  transform: translateX(-50%);
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: var(--accent-ink);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.06em;
  border-radius: 999px;
  padding: 4px 14px;
  white-space: nowrap;
}
.price-card h3 { font-size: 18px; color: var(--text-strong); }
.price-card .price { margin: 12px 0 2px; }
.price-card .price b { font-family: var(--display); font-size: 30px; color: var(--text-strong); letter-spacing: -0.01em; }
.price-card .price span { font-size: 13.5px; color: var(--muted); display: block; }
.price-card ul { list-style: none; margin: 18px 0 22px; flex: 1; }
.price-card li {
  padding-left: 26px; position: relative;
  margin-bottom: 9px;
  font-size: 14.5px; color: var(--muted);
}
.price-card li::before {
  content: "✓";
  position: absolute; left: 2px;
  color: var(--accent);
  font-weight: 700;
}
.price-card .btn { justify-content: center; }

/* ---------- market switch ----------
   Two price sets, one per market, with the chooser sitting UNDER the grid.
   Driven by radio inputs and the sibling combinator, so it works with
   JavaScript disabled and keeps real keyboard semantics — a segmented
   control that is actually a radio group, not divs with click handlers. */
.market-switch { position: relative; }
.market-switch > input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}
.market-panel { display: none; }
.market-switch > input.mk-a:checked ~ .market-panels .market-panel.mk-a,
.market-switch > input.mk-b:checked ~ .market-panels .market-panel.mk-b {
  display: block;
}

/* The personal tier is deliberately a strip, not a fourth card. A cheap card
   sitting in the same row would re-anchor every business quote down to it. */
.price-aside {
  margin-top: 16px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 26px;
  padding: 20px 24px;
  border: 1px dashed var(--panel-edge);
  border-radius: var(--radius);
  background: var(--bg-raise);
}
.price-aside .pa-main { flex: 1 1 320px; min-width: 0; }
.price-aside h3 { font-size: 15.5px; color: var(--text-strong); margin-bottom: 5px; }
.price-aside p { font-size: 13.5px; color: var(--muted); margin: 0; }
.price-aside .pa-price {
  font-family: var(--display);
  font-size: 22px;
  color: var(--text-strong);
  white-space: nowrap;
}
.price-aside .btn { padding: 10px 18px; font-size: 14px; }
@media (max-width: 640px) { .price-aside { padding: 18px; } .price-aside .btn { width: 100%; justify-content: center; } }

.market-choose {
  margin: 26px auto 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  padding: 7px;
  width: max-content;
  max-width: 100%;
  border: 1px solid var(--panel-edge);
  border-radius: 999px;
  background: var(--bg-raise);
}
.market-choose label {
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: 0.01em;
  color: var(--muted);
  padding: 9px 18px;
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
  transition: color var(--dur-micro) var(--ease-out),
              background var(--dur-micro) var(--ease-out);
}
.market-choose label:hover { color: var(--text-strong); }
.market-switch > input.mk-a:checked ~ .market-choose label[data-for="a"],
.market-switch > input.mk-b:checked ~ .market-choose label[data-for="b"] {
  background: var(--accent);
  color: var(--accent-ink);
}
/* the focus ring has to follow the visually hidden input onto its label */
.market-switch > input.mk-a:focus-visible ~ .market-choose label[data-for="a"],
.market-switch > input.mk-b:focus-visible ~ .market-choose label[data-for="b"] {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.market-note {
  margin: 14px auto 0;
  max-width: 62ch;
  text-align: center;
  font-size: 13.5px;
  color: var(--muted);
}
@media (max-width: 560px) {
  .market-choose { width: 100%; justify-content: stretch; }
  .market-choose label { flex: 1; text-align: center; padding: 10px 12px; }
}

/* util */
.center { text-align: center; }
.mt-lg { margin-top: 48px; }


/* ---------- print ---------- */

@media print {
  :root {
    --bg: #fff;
    --bg-raise: #fff;
    --panel: #fff;
    --panel-edge: #bbb;
    --text: #111;
    --text-strong: #000;
    --muted: #444;
    --accent: #111;
    --accent-soft: transparent;
    --accent-edge: #bbb;
  }
  body { background: #fff; color: var(--text); }
  .floating-menu, .wa-float, .skip-link { display: none !important; }
  .hero, .hero.hero-cinema, section.block.photo-bg, section.block.glow-bg, section.block.alt { background: #fff; }
  .hero::before, .hero::after { display: none; }
  .hero h1 .hl { background: none; -webkit-background-clip: initial; background-clip: initial; color: var(--text-strong); }
  .card, .price-card, .stat, .faq details { border: 1px solid #ccc; box-shadow: none; }
  a { color: #111; text-decoration: underline; }
}


/* ============================================================
   Signature layer — grain, spotlight, marquee, reveals, bento
   ============================================================ */

/* film grain: the single cheapest way to stop a dark UI reading as flat */
.grain {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* cursor spotlight over the hero */
.hero .spotlight {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(520px circle at var(--hx, 70%) var(--hy, 30%), rgba(255, 255, 255, 0.10), transparent 60%);
  opacity: 0;
  transition: opacity 0.5s ease;
}
.hero:hover .spotlight { opacity: 1; }

/* availability pill */
/* Availability, stated instead of signalled. The pulsing light was a dashboard
   cliché, and once the palette lost green it was just a white bulb flashing on
   a luxury page. A square end and a solid left rule read as a label. */
.hero-note {
  display: inline-flex;
  align-items: center;
  margin-top: 22px;
  padding: 9px 18px;
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: 0.02em;
  color: var(--text);
  border: 1px solid var(--panel-edge);
  border-left: 2px solid var(--accent);
  border-radius: 3px;
  background: rgba(14, 14, 14, 0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.footer-status {
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: 0.02em;
  padding-left: 11px;
  border-left: 2px solid var(--accent);
}
@keyframes pulse {
  70% { box-shadow: 0 0 0 9px rgba(255, 255, 255, 0); }
  100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
}

/* tech ticker */
.marquee {
  margin-top: 34px;
  overflow: hidden;
  border-top: 1px solid var(--panel-edge);
  border-bottom: 1px solid var(--panel-edge);
  padding: 13px 0;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.marquee-track {
  display: flex;
  width: max-content;
  animation: marquee 46s linear infinite;
}
.marquee span {
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: 0.04em;
  color: var(--muted);
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
}
.marquee span::after {
  content: "◆";
  color: var(--accent);
  opacity: 0.45;
  font-size: 7px;
  margin: 0 24px;
}
@keyframes marquee { to { transform: translateX(-50%); } }

@media (prefers-reduced-motion: reduce) {
  .marquee-track { animation: none; }
}

/* bento: the featured service tile spans two columns */
@media (min-width: 760px) {
  .grid.bento { grid-template-columns: repeat(3, 1fr); }
  .grid.bento .card.wide { grid-column: span 2; }
}
.card.wide h3 { font-size: 22px; }

/* process timeline */
.steps { position: relative; }
/* .step used to be a bare list item with a hanging counter; it is a .card now,
   so it must keep the card's padding instead of clearing it. */
@media (min-width: 900px) {
  .steps::before {
    content: "";
    position: absolute;
    top: 44px; left: 6%; right: 6%;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--accent-edge), var(--accent-edge), transparent);
    z-index: 0;
  }
}
.step::before {
  display: inline-grid !important;
  place-items: center;
  width: 34px; height: 34px;
  border-radius: 50%;
  border: 1px solid var(--accent-edge);
  background: var(--bg-raise);
  color: var(--accent);
  font-size: 12px;
  margin-bottom: 16px;
}

/* section eyebrow gets a rule, so headings feel authored */
.section-head .eyebrow::before {
  content: "";
  display: inline-block;
  width: 26px;
  height: 1px;
  background: var(--accent);
  vertical-align: middle;
  margin-right: 11px;
}

/* ============================================================
   Signature — "Instrument": a live miniature of the real product
   ============================================================ */

.who {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 22px;
  font-size: 13.5px;
  color: var(--muted);
}
.who img {
  width: 36px; height: 36px;
  border-radius: 50%;
  object-fit: cover;
  object-position: 50% 30%;
  border: 1px solid var(--panel-edge);
  box-shadow: var(--shadow-1);
  filter: grayscale(1) contrast(1.04);
}
.who b { color: var(--text-strong); font-weight: 600; }

/* ---------- signature ----------
   A drawn mark, not a font: each stroke carries pathLength="1", so the dash
   maths is resolution-independent and no JS is needed to measure anything.
   The strokes overlap heavily — the whole name is written in ~1.1s, which is
   the "fast motion" of a real signature rather than a slow reveal. */
.sig {
  width: 186px;
  height: auto;
  display: block;
  overflow: visible;
  color: var(--text-strong);
}
.sig path {
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.sig .cap { stroke-width: 5.4; }
.sig .low { stroke-width: 4.6; }
.sig .thin { stroke-width: 3.4; }
.sig .fl { stroke-width: 3.8; }

@media (prefers-reduced-motion: no-preference) {
  .sig path {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    animation: sig-write 260ms var(--ease-out) forwards;
    animation-delay: calc(var(--i) * 42ms + 140ms);
  }
  /* the closing flourish is one long sweep, so it gets its own longer beat */
  .sig .fl { animation-duration: 420ms; }
}
@keyframes sig-write { to { stroke-dashoffset: 0; } }

.who .sig { margin-bottom: -2px; }
@media (max-width: 900px) { .sig { width: 158px; } }
.who span::before { content: "·"; margin: 0 7px; opacity: 0.6; }

.instrument { margin: 0; width: 360px; max-width: 100%; }
.instrument-frame {
  background: var(--panel);
  border: 1px solid var(--panel-edge);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: var(--shadow-lift);
}
.instrument-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 14px;
  background: var(--bg-raise);
  border-bottom: 1px solid var(--panel-edge);
}
.instrument-lights {
  width: 38px; height: 8px;
  border-radius: 99px;
  background:
    radial-gradient(circle 4px at 4px 4px, rgba(255,255,255,0.55) 98%, transparent),
    radial-gradient(circle 4px at 19px 4px, rgba(255,255,255,0.34) 98%, transparent),
    radial-gradient(circle 4px at 34px 4px, rgba(255,255,255,0.2) 98%, transparent);
  flex-shrink: 0;
}
.instrument-url {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--muted);
  flex: 1;
}
.instrument-badge {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--green);
  background: var(--green-soft);
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 99px;
  padding: 2px 8px;
}
.instrument-body { padding: 22px 22px 20px; }

.order-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 14px;
  padding-bottom: 15px;
  border-bottom: 1px solid var(--panel-edge);
}
.order-dish { display: block; font-size: 15px; color: var(--text-strong); font-weight: 600; }
.order-cook { display: block; margin-top: 3px; font-size: 12.5px; color: var(--muted); }
.order-price { font-family: var(--mono); font-size: 15px; color: var(--accent); white-space: nowrap; }

.pipeline { list-style: none; margin: 16px 0 0; padding: 0 0 0 24px; position: relative; }
.pipeline::before {
  content: "";
  position: absolute;
  left: 5px; top: 8px; bottom: 8px;
  width: 1px;
  background: var(--panel-edge);
}
.pipeline li {
  position: relative;
  font-size: 13.5px;
  line-height: 1.5;
  padding: 5px 0;
  color: var(--muted);
  opacity: 0.45;
  transition: opacity var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}
.pipeline li::before {
  content: "";
  position: absolute;
  left: -24px; top: 12px;
  width: 11px; height: 11px;
  border-radius: 50%;
  border: 1px solid var(--panel-edge);
  background: var(--panel);
  transition: border-color var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-spring);
}
.pipeline li.done { opacity: 1; color: var(--text); }
.pipeline li.done::before { border-color: var(--accent-edge); background: var(--accent-soft); }
.pipeline li.now { opacity: 1; color: var(--text-strong); font-weight: 500; }
.pipeline li.now::before {
  border-color: var(--accent);
  background: var(--accent);
  transform: scale(1.18);
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.16);
}

.instrument-log {
  margin-top: 15px;
  padding-top: 13px;
  border-top: 1px solid var(--panel-edge);
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.instrument figcaption {
  margin-top: 13px;
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--muted);
  max-width: 360px;
}

@media (max-width: 900px) {
  .instrument { width: 100%; max-width: 420px; }
}

/* ---------- locale-aware type + phone ergonomics ---------- */

/* Indonesian headlines run ~25% longer and break less gracefully; the English
   line length is not a safe default for them. */
html[lang="id"] .hero h1 { font-size: clamp(29px, 5.4vw, 64px); }
html[lang="id"] .section-head h2 { font-size: clamp(25px, 3.4vw, 38px); }

@media (max-width: 620px) {
  .hero h1 { font-size: clamp(31px, 8.6vw, 44px); }
  html[lang="id"] .hero h1 { font-size: clamp(27px, 7.6vw, 38px); }

  /* one-thumb targets */
  .cta-row { gap: 10px; }
  .cta-row .btn { width: 100%; justify-content: center; }
  .hero { padding: 76px 0 56px; }

  /* keep the last CTA clear of the floating WhatsApp button */
  section.block:last-of-type { padding-bottom: 108px; }
}

/* ---------- capability index (replaces the icon-card feature grid) ---------- */

.index { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--panel-edge); }
.index-row { border-bottom: 1px solid var(--panel-edge); }
.index-row a {
  display: grid;
  grid-template-columns: 3.4rem minmax(0, 1fr) auto 1.6rem;
  align-items: baseline;
  gap: 8px 20px;
  padding: 26px 14px 26px 10px;
  color: inherit;
  position: relative;
  transition: background var(--dur-base) var(--ease-out), padding-left var(--dur-base) var(--ease-out);
}
.index-row a:hover, .index-row a:focus-visible {
  text-decoration: none;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.055), transparent 62%);
  padding-left: 20px;
}
.index-num {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--muted);
  transition: color var(--dur-base) var(--ease-out);
}
.index-row a:hover .index-num { color: var(--accent); }
.index-name {
  display: block;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(20px, 2.4vw, 27px);
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--text-strong);
}
.index-desc {
  display: block;
  margin-top: 7px;
  font-size: 15px;
  line-height: 1.55;
  color: var(--muted);
  max-inline-size: 52ch;
}
.index-meta {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--muted);
  opacity: 0.75;
  white-space: nowrap;
  justify-self: end;
}
.index-arrow {
  font-size: 17px;
  color: var(--accent);
  opacity: 0;
  transform: translateX(-6px);
  justify-self: end;
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-spring);
}
.index-row a:hover .index-arrow, .index-row a:focus-visible .index-arrow {
  opacity: 1;
  transform: translateX(0);
}

@media (max-width: 860px) {
  .index-row a {
    grid-template-columns: 2.6rem minmax(0, 1fr);
    gap: 4px 14px;
    padding: 22px 10px;
  }
  .index-meta { grid-column: 2; justify-self: start; margin-top: 9px; white-space: normal; }
  .index-arrow { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .index-row a, .index-arrow { transition: none; }
}

/* Phones get a 44 KB crop of the hero backdrop instead of the 124 KB one —
   Indonesia is a mid-range-Android-on-congested-4G market. */
@media (max-width: 760px) {
  .hero.hero-cinema {
    background:
      linear-gradient(180deg, rgba(8, 8, 8, 0.94) 0%, rgba(8, 8, 8, 0.84) 45%, rgba(8, 8, 8, 0.97) 100%),
      linear-gradient(180deg, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0.03)),
      url("/assets/borobudur-stupas-sm.jpg") center 32% / cover no-repeat;
  }
  section.block.photo-bg {
    background:
      linear-gradient(180deg, rgba(8, 8, 8, 0.94), rgba(8, 8, 8, 0.84) 45%, rgba(8, 8, 8, 0.95)),
      url("/assets/borobudur-stupas-sm.jpg") center 78% / cover no-repeat;
  }
}

/* Formspree honeypot: bots fill it, humans never see it. Not display:none —
   some bots skip fields that are display:none. */
.hp {
  position: absolute !important;
  left: -9999px !important;
  width: 1px !important;
  height: 1px !important;
  opacity: 0 !important;
  pointer-events: none !important;
}

/* ---------- real product screenshots (Celina) ---------- */

/* The browser frame is now a link: clicking the product opens the product. */
a.browser {
  display: block;
  color: inherit;
  transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
a.browser:hover {
  text-decoration: none;
  transform: translateY(-3px);
  box-shadow: var(--shadow-lift);
}
a.browser:hover .browser-url { color: var(--accent); }
.browser .shot {
  display: block;
  width: 100%;
  height: auto;
  border-top: 1px solid var(--panel-edge);
}
.browser-live {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--green);
  background: var(--green-soft);
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 99px;
  padding: 2px 8px;
  white-space: nowrap;
}

/* two screenshots side by side on the case-study page */
.shots {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
  margin: 30px 0 8px;
  align-items: start;
}
@media (max-width: 760px) { .shots { grid-template-columns: 1fr; } }
.shots figure { margin: 0; }
.shots figcaption {
  margin-top: 10px;
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--muted);
}

/* ---------- hero: real mobile screenshot instead of the built pipeline ---------- */

.hero-shot {
  width: 248px;
  height: auto;
  max-width: 100%;
  /* 26px on a 248px-wide shot bit into the app's white header bar and read as
     a crop; 12px still frames it as a device without eating the content. */
  border-radius: 12px;
  border: 1px solid var(--panel-edge);
  box-shadow: var(--shadow-lift);
  display: block;
  transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
figure.instrument { display: flex; flex-direction: column; align-items: center; }
a.hero-shot-link { display: block; width: max-content; max-width: 100%; }
a.hero-shot-link:hover { text-decoration: none; }
a.hero-shot-link:hover .hero-shot { transform: translateY(-4px); }
.hero-shot-cap {
  margin-top: 14px;
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--muted);
  /* exactly the image width, centred under it — the caption used to be 12px
     wider and left-aligned, which threw the whole column off axis */
  width: 248px;
  max-width: 100%;
  text-align: center;
}
.hero-shot-cap b { color: var(--green); font-weight: 400; }
@media (max-width: 900px) {
  .hero-shot { width: 210px; border-radius: 11px; }
  .hero-shot-cap { width: 210px; }
}
@media (max-width: 460px) {
  .sig { width: 112px; }
  .who { gap: 8px; font-size: 12.5px; }
  /* at 112px the 3.4-unit hairlines resolve under one device pixel and smear */
  .sig .thin { stroke-width: 5.2; }
  .sig .fl { stroke-width: 5; }
  .sig .low { stroke-width: 5.8; }
  .sig .cap { stroke-width: 6.4; }
}

/* ---------- portfolio: two projects, real screens ---------- */

.project { border-top: 1px solid var(--panel-edge); padding-top: 34px; margin-top: 34px; }
.project:first-of-type { border-top: none; padding-top: 0; margin-top: 0; }
.project-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px 16px; margin-bottom: 8px; }
.project-head h3 { font-size: clamp(21px, 2.6vw, 27px); letter-spacing: -0.02em; color: var(--text-strong); }
.project-role { font-family: var(--mono); font-size: 11.5px; color: var(--muted); }
.project-lead { color: var(--muted); font-size: 15.5px; max-inline-size: 62ch; margin-bottom: 16px; }
.project-shots {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px;
  margin: 18px 0;
  align-items: start;
}
/* Each frame takes the shape of its own screenshot: no crop, no letterbox, the
   whole product visible at its true proportions. A forced aspect ratio either
   cuts the image (cover) or pads it with empty bars (contain) — both are worse
   than frames of slightly different heights, which top-align and read as
   deliberate. */
.project-shots .shot,
.shots .shot {
  width: 100%;
  height: auto;
  display: block;
}
.project-links { display: flex; flex-wrap: wrap; gap: 12px 26px; font-family: var(--mono); font-size: 13px; margin-top: 16px; }


/* a price anchor on the pages that actually rank */
.price-line {
  margin-top: 14px;
  padding: 14px 18px;
  border-left: 2px solid var(--accent-edge);
  background: var(--bg-raise);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 15px;
  color: var(--text);
  max-inline-size: 68ch;
}
.price-line b { color: var(--text-strong); }


/* Autofill: the only way to beat Chrome's own fill is an inset shadow. */
.field input:-webkit-autofill,
.field input:-webkit-autofill:hover,
.field input:-webkit-autofill:focus,
.field textarea:-webkit-autofill {
  -webkit-text-fill-color: var(--text-strong);
  caret-color: var(--text-strong);
  -webkit-box-shadow: 0 0 0 1000px var(--bg) inset;
  box-shadow: 0 0 0 1000px var(--bg) inset;
  transition: background-color 9999s ease-in-out 0s;
}
