/* ============================================================
   Emmanuel Torres — Product Designer
   Design tokens taken from the Figma source.
   ============================================================ */

:root {
  color-scheme: dark;

  /* colour — dark (default). Light overrides live in the block below;
     every pair is contrast-audited by `node tools/contrast.mjs`. */
  --bg:            #0b1017;
  --panel:         #131522;
  --panel-hover:   #1a1d2e;
  --border:        rgba(255, 255, 255, 0.08);
  --text:          #f2f4f5;
  --text-hero:     #dadae6;
  --text-muted:    #9d9eab;
  --text-muted-2:  #b8b8b8;
  --text-faint:    #949aa6;
  --text-role:     #8a9099;
  --accent:        #3ea6ff;
  --highlight:     rgba(255, 89, 0, 0.08);
  --field-bg:      rgba(255, 255, 255, 0.03);
  --field-bg-focus:rgba(255, 255, 255, 0.05);
  --field-border:  #656a7a;   /* >= 3:1 on bg and panel (WCAG 1.4.11) */
  --danger:        #ff8a7f;
  --danger-border: #ff6b5e;

  /* The case-card artwork is baked dark in BOTH themes, so anything sitting
     on top of it keeps a fixed light treatment and never flips. */
  --on-artwork:    #f2f4f5;
  --btn-bg:        #f2f4f5;
  --btn-fg:        #001666;

  /* layout */
  --shell:         1200px;
  --gutter:        clamp(20px, 5vw, 48px);
  --section-gap:   clamp(72px, 10vw, 160px);
  --radius-card:   16px;
}

:root[data-theme="light"] {
  color-scheme: light;

  --bg:            #f7f8fa;
  --panel:         #ffffff;
  --panel-hover:   #eef0f5;
  --border:        rgba(15, 19, 32, 0.12);
  --text:          #0f1320;
  --text-hero:     #1a1f30;
  --text-muted:    #55596b;
  --text-muted-2:  #4e5263;
  --text-faint:    #5f6472;
  --text-role:     #646978;
  --accent:        #0a5ec4;
  --highlight:     rgba(255, 89, 0, 0.16);
  --field-bg:      rgba(15, 19, 32, 0.03);
  --field-bg-focus:rgba(15, 19, 32, 0.05);
  --field-border:  #858a97;
  --danger:        #b3261e;
  --danger-border: #b3261e;
}

/* Theme flips shouldn't animate on load, only on an actual toggle. */
:root.theme-animating,
:root.theme-animating * {
  transition: background-color .25s ease, border-color .25s ease, color .25s ease !important;
}

/* ---------------------------- font ---------------------------- */
/* Self-hosted. Only the Regular cut exists, so bold text is synthesised by the
   browser. ← and ★ aren't in this file and fall back to the system font. */
@font-face {
  font-family: 'Apercu';
  src: url('assets/fonts/Apercu-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ------------------------- smooth scroll ------------------------- */
/* Lenis' own stylesheet (4 rules) — inlined rather than loaded separately. */

html.lenis,
html.lenis body { height: auto; }

.lenis.lenis-smooth { scroll-behavior: auto !important; }

.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }

.lenis.lenis-stopped { overflow: hidden; }

/* ---------------------------- reset ---------------------------- */

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: 'Apercu', ui-sans-serif, system-ui, -apple-system, 'Segoe UI',
               Helvetica, Arial, sans-serif;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

h1, h2, h3, h4, p, figure, blockquote, ul { margin: 0; }
ul { padding: 0; list-style: none; }
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  padding: 12px 20px;
  background: var(--text);
  color: var(--bg);
  border-radius: 0 0 12px 0;
  z-index: 200;                 /* above the sticky top bars (100) */
}
.skip-link:focus { left: 0; }

/* All page content shares one stacking layer at level 0. The sticky top bars
   live outside <main>, so nothing inside it — cards, videos, animated
   sections — can ever paint over them. */
main {
  position: relative;
  z-index: 0;
  isolation: isolate;
}

.shell {
  width: 100%;
  max-width: calc(var(--shell) + var(--gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.br-lg { display: none; }

/* ---------------------------- header ---------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;                 /* above <main>'s single layer (see above) */
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(12.5px);
  -webkit-backdrop-filter: blur(12.5px);
}

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  height: 88px;
  padding-inline: clamp(20px, 5.6vw, 108px);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

.brand__avatar {
  width: 48px;
  height: 48px;
  border-radius: 9999px;
  object-fit: cover;
  flex: none;
}

.brand__name {
  font-size: 20px;
  line-height: 24px;
  letter-spacing: -0.4px;
  color: var(--text);
  white-space: nowrap;
}

.nav__link {
  font-size: 18px;
  line-height: 21px;
  letter-spacing: -0.3px;
  color: var(--text);
  transition: opacity .2s ease;
}
.nav__link:hover { opacity: .7; }

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

.hero {
  padding-top: clamp(56px, 7vw, 80px);
  padding-bottom: var(--section-gap);
  text-align: center;
}

.hero__title {
  max-width: 1080px;
  margin-inline: auto;
  font-size: clamp(2.25rem, 1.1rem + 4.75vw, 4.5rem);   /* 36 → 72 */
  line-height: 1.2;
  letter-spacing: -0.06em;
  font-weight: 400;
  color: var(--text-hero);
  text-wrap: balance;
}

.hero__sub {
  max-width: 720px;
  /* Matches the reference: title's last line → paragraph is 92px cap-to-cap,
     paragraph lines 33.6px apart (1.4 × 24px). */
  margin: clamp(10px, 1vw, 14px) auto 0;
  font-size: clamp(1rem, 0.82rem + 0.75vw, 1.5rem);     /* 16 → 24 */
  line-height: 1.4;
  letter-spacing: -0.0125em;
  color: var(--text-muted);
  text-wrap: pretty;
}

/* ----------------------------- work ----------------------------- */

.work__list {
  display: grid;
  gap: 40px;
}

.case {
  position: relative;
  display: block;
  border-radius: var(--radius-card);
  overflow: hidden;
  isolation: isolate;
  aspect-ratio: 1200 / 641;
  color: var(--on-artwork);
}

.case__media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  z-index: -2;
  pointer-events: none;
}

/* scrim only exists on the stacked (narrow) layout — see media queries */
.case::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0;
  background: linear-gradient(
    to top,
    rgba(11, 16, 23, .95) 0%,
    rgba(11, 16, 23, .90) 42%,
    rgba(11, 16, 23, .62) 72%,
    rgba(11, 16, 23, .30) 100%
  );
  transition: opacity .2s ease;
}

.case__body {
  position: absolute;
  top: 50%;
  left: clamp(28px, 4vw, 48px);
  transform: translateY(-50%);
  width: min(480px, 44%);
}

.case__text {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.case__eyebrow,
.case__meta {
  font-size: clamp(1rem, 0.94rem + 0.25vw, 1.25rem);    /* 16 → 20 */
  line-height: 1.2;
  letter-spacing: -0.03em;
  color: var(--on-artwork);
  opacity: .75;
}

.case__title {
  font-size: clamp(1.75rem, 1.05rem + 2.1vw, 3rem);     /* 28 → 48 */
  line-height: 1.2;
  letter-spacing: -0.03em;
  font-weight: 400;
  color: var(--on-artwork);
  text-wrap: balance;
}
.case__title b { font-weight: 700; }

/* ----- pill button ----- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 40px;
  padding: 0 24px;
  height: 56px;
  border-radius: 99px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-size: 18px;
  line-height: 21px;
  white-space: nowrap;
  transition: transform .2s ease, background-color .2s ease;
}

.btn img { flex: none; }

.case:is(a):hover .btn { background: #fff; transform: translateY(-2px); }

.btn--muted {
  opacity: .5;
  cursor: default;
}

/* ----- "AI-Accelerated Workflow" badge ----- */

.badge {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  height: 44px;
  padding: 0 24px;
  gap: 12px;
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: 7px;
  background: linear-gradient(rgba(255, 255, 255, .05), rgba(255, 255, 255, .05)), #000;
  box-shadow: 0 24px 24px rgba(0, 0, 0, .3);
  backdrop-filter: blur(12.5px);
  -webkit-backdrop-filter: blur(12.5px);
}

.badge__dot {
  width: 7px;
  height: 7px;
  border-radius: 7px;
  background: var(--accent);
  flex: none;
}

.badge__label {
  position: relative;
  font-size: 16px;
  line-height: 19px;
  letter-spacing: -0.32px;
  color: #fff;
  white-space: nowrap;
}

/* the Framer "text shine" sweep */
.badge__label::after {
  content: attr(data-text);
  position: absolute;
  inset: 0;
  color: transparent;
  background-image: linear-gradient(
    100deg,
    transparent 35%,
    var(--accent) 48%,
    #d8f7d6 52%,
    transparent 65%
  );
  background-size: 300% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  animation: shine 4.5s linear infinite;
  pointer-events: none;
}

@keyframes shine {
  from { background-position: 150% 0; }
  to   { background-position: -150% 0; }
}

/* -------------------------- testimonials -------------------------- */

.section-head__title {
  font-size: clamp(2rem, 1.3rem + 2.9vw, 4rem);         /* 32 → 64 */
  line-height: 1.2;
  letter-spacing: -0.027em;
  font-weight: 400;
  color: var(--text);
  text-wrap: balance;
}

.section-head__sub {
  margin-top: 13px;
  font-size: clamp(1rem, 0.94rem + 0.25vw, 1.25rem);
  line-height: 1.2;
  letter-spacing: -0.03em;
  color: var(--text-muted);
  text-wrap: pretty;
}

.quotes__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
  gap: 32px;
  margin-top: clamp(40px, 6vw, 96px);
}

.quote {
  padding: 41px 32px 32px;
  border-radius: var(--radius-card);
}

.quote__text {
  font-size: clamp(1.0625rem, 1rem + 0.3vw, 1.25rem);   /* 17 → 20 */
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--text-muted);
}

.quote__text mark {
  background: linear-gradient(to right, var(--highlight), var(--highlight) 55%, rgba(255, 89, 0, 0));
  color: var(--text);
  border-radius: 2px;
  padding: 1px 0;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

.quote__by {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-top: clamp(28px, 4vw, 43px);
}

.quote__name {
  font-size: 18px;
  line-height: 21px;
  letter-spacing: -0.3px;
  color: var(--text);
}

.quote__role {
  font-size: 14px;
  line-height: 16px;
  letter-spacing: -0.1px;
  color: var(--text-role);
}

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

.quotes,
.contact { padding-top: var(--section-gap); }

.contact { padding-bottom: var(--section-gap); }

.contact__inner {
  display: grid;
  grid-template-columns: minmax(0, 660px) minmax(0, 500px);
  justify-content: space-between;
  gap: 40px;
}

.contact__lede {
  margin-top: 25px;
  max-width: 494px;
  font-size: clamp(1rem, 0.95rem + 0.2vw, 1.125rem);    /* 16 → 18 */
  line-height: 1.4;
  letter-spacing: -0.017em;
  color: var(--text-muted-2);
}
.contact__lede + .contact__lede { margin-top: 25px; }

.contact__links {
  display: grid;
  gap: 8px;
  align-content: start;
}

.contact__links a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 65px;
  padding: 12px 25px;
  border-radius: var(--radius-card);
  background: var(--panel);
  font-size: 14px;
  line-height: 16px;
  letter-spacing: -0.1px;
  color: var(--text);
  transition: background-color .2s ease;
}
.contact__links a:hover { background: var(--panel-hover); }

.contact__value {
  text-align: right;
  word-break: break-word;
}

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

.site-footer {
  padding-top: var(--section-gap);
  padding-bottom: 32px;
}

.site-footer__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}

.site-footer__copy {
  font-size: 16px;
  line-height: 19px;
  color: var(--text);
}
.site-footer__copy span { color: var(--text-faint); }

.site-footer__links {
  display: flex;
  gap: 32px;
}

.site-footer__links a {
  font-size: 14px;
  line-height: 16px;
  letter-spacing: -0.1px;
  color: var(--text);
  transition: opacity .2s ease;
}
.site-footer__links a:hover { opacity: .65; }

/* =========================== responsive =========================== */

/* The design's hero break ("...products with" / "AI in the loop...") only
   fits on one line once there is room for it; below that it wraps naturally. */
@media (min-width: 1300px) {
  .br-lg { display: inline; }
}

/* Below the design width the 1200px canvas scales fluidly;
   the case cards keep their side-by-side composition until 1024px. */
@media (max-width: 1180px) {
  .btn { margin-top: clamp(20px, 3vw, 40px); }
  .case__text { gap: clamp(10px, 1.4vw, 16px); }
}

@media (max-width: 1023px) {
  /* Stack: the artwork becomes a full-bleed backdrop and the copy
     sits on a scrim at the bottom of the card. */
  .case {
    aspect-ratio: auto;
    min-height: 520px;
    width: 100%;
    display: flex;
    align-items: flex-end;
  }
  .case::after { opacity: 1; }
  .case__media { object-position: 68% center; }
  .case__body {
    position: static;
    transform: none;
    width: 100%;
    padding: 32px 28px;
  }

  .contact__inner {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(32px, 6vw, 48px);
  }
  .contact__lede { max-width: 60ch; }
}

@media (max-width: 767px) {
  .work__list { gap: 24px; }

  .quotes__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
  }
  .quote { padding: 0; }

  .site-footer__inner {
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
  }
  .site-footer__links { gap: 24px; }

  .nav { height: 72px; }
  .brand__avatar { width: 40px; height: 40px; }
  .brand__name { font-size: 17px; }
  .nav__link { font-size: 16px; }
}

@media (max-width: 520px) {
  .case { min-height: 480px; }
  .case__body { padding: 24px 20px; }
  .btn { height: 50px; font-size: 16px; padding: 0 20px; }
  .btn img { width: 20px; height: 20px; }
  .badge { height: 40px; padding: 0 12px; }
  .badge__label { font-size: 14px; }
  .contact__links a {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    padding: 16px 20px;
  }
  .contact__value { text-align: left; }
}

/* ---------------------------- a11y prefs ---------------------------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* ------------------------- theme toggle ------------------------- */

.theme-toggle {
  display: inline-grid;
  place-items: center;
  width: 44px;                 /* WCAG 2.5.5 target size */
  height: 44px;
  flex: none;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: transparent;
  color: var(--text);
  cursor: pointer;
  transition: background-color .2s ease, border-color .2s ease, color .2s ease;
}

.theme-toggle:hover {
  background: var(--panel);
  border-color: var(--text-muted);
}

.theme-toggle svg {
  width: 20px;
  height: 20px;
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Show the icon for the theme you'd switch TO. */
.theme-toggle .icon-sun  { display: none; }
.theme-toggle .icon-moon { display: block; }
:root[data-theme="light"] .theme-toggle .icon-sun  { display: block; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: none; }

/* Sits between the brand and Contact in the home nav. */
.nav__end {
  display: flex;
  align-items: center;
  gap: clamp(12px, 2vw, 24px);
}

/* In light mode the white panels sit on an off-white page (1.07:1), so give
   them a hairline so the boundary is perceivable (WCAG 1.4.11). An inset ring
   rather than a border, so nothing reflows. Dark mode keeps the Figma look. */
:root[data-theme="light"] .contact__links a {
  box-shadow: inset 0 0 0 1px var(--border);
}

/* ------------------------ card background video ------------------------ */

.case-item { position: relative; }

/* Pause/play for the looping card video (WCAG 2.2.2). It sits over the
   artwork, so like the other artwork chrome it keeps a fixed dark treatment. */
.case__motion {
  position: absolute;
  right: 16px;
  bottom: 16px;
  z-index: 2;
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, .22);
  border-radius: 999px;
  background: rgba(11, 16, 23, .55);
  color: var(--on-artwork);
  cursor: pointer;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  transition: background-color .2s ease;
}
.case__motion:hover { background: rgba(11, 16, 23, .8); }
.case__motion[hidden] { display: none; }

.case__motion svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.case__motion .icon-play { fill: currentColor; stroke: none; display: none; }
.case__motion[aria-pressed="true"] .icon-pause { display: none; }
.case__motion[aria-pressed="true"] .icon-play  { display: block; }

/* Narrow phones (≤400px): brand + theme toggle + Contact ran 14px over at
   320px once Apercu (wider than Satoshi) and the toggle shared the row.
   Tighten the gaps; the toggle keeps its full 44px tap target. */
@media (max-width: 400px) {
  .nav        { gap: 12px; }
  .nav__end   { gap: 8px; }
  .brand      { gap: 8px; }
  .brand__name { font-size: 16px; }
}

/* ---------------------------- fade-in reveal ---------------------------- */
/* html.reveal-on is set by a tiny inline script in <head>, BEFORE first paint,
   so targets start hidden instead of flashing visible and then vanishing.
   assets/js/reveal.js then adds .is-revealed on load (hero) or on scroll.
   Keep this selector list in sync with the one in reveal.js. If reveal.js
   never loads, the inline script removes .reveal-on after 4s. */
.reveal-on :is(
  .hero__sub, .work__list > li, .section-head, .quotes__grid > *, .contact__inner > *,
  .cs-hero__inner > :not(.cs-hero__title), .cs-media--hero, .cs-lead, .cs-duo > *,
  .cs-trio > *, .cs-role, .cs-filmstrip, .cs-scroller--reviews, .cs-showcase, .cs-reviews-panel,
  .cs-feature,
  .cs-next__label, .cs-next .case
):not(.is-revealed) {
  opacity: 0;
  transform: translateY(16px);
}

/* Hero titles stay hidden until reveal.js has split them into words. */
.reveal-on :is(.hero__title, .cs-hero__title):not([data-reveal]) { opacity: 0; }

/* The transition lives on the revealed state, so hiding is instant and only
   the reveal animates. */
.reveal-on [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  transition:
    opacity .8s cubic-bezier(.2, .7, .2, 1) var(--reveal-delay, 0ms),
    transform .8s cubic-bezier(.2, .7, .2, 1) var(--reveal-delay, 0ms);
}

/* Hero titles: the heading itself stays put; its words fade up in turn. */
.reveal-on [data-reveal="words"] { opacity: 1; transform: none; }
.reveal-on [data-reveal="words"] .reveal-word {
  display: inline-block;          /* lets each word move independently */
  opacity: 0;
  transform: translateY(0.3em);
}
.reveal-on [data-reveal="words"].is-revealed .reveal-word {
  opacity: 1;
  transform: none;
  transition:
    opacity .5s cubic-bezier(.2, .7, .2, 1) var(--word-delay, 0ms),
    transform .5s cubic-bezier(.2, .7, .2, 1) var(--word-delay, 0ms);
}

/* ---------------------------- page exit ---------------------------- */
/* assets/js/page-exit.js adds html.is-leaving when a case card is clicked.
   The content fades; the body background stays, so there's no flash. */
.is-leaving body > * {
  opacity: 0;
  transition: opacity .2s ease;
}

/* ============================================================
   Password gate
   Every published page is generated by tools/lock.mjs: it shows this
   form until the password decrypts the page. One unlock covers the
   whole site (the key is remembered in localStorage).
   ============================================================ */

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.gate {
  display: grid;
  place-items: center;
  min-height: 100svh;
  padding: var(--gutter);
}

/* Returning visitors: a stored key is being tried — hold the form back so it
   doesn't flash before the page appears. Shown again if the key fails. */
.gate-auto .gate { visibility: hidden; }

.gate__form {
  display: grid;
  justify-items: center;
  width: 100%;
  max-width: 400px;
  text-align: center;
}

.gate__icon {
  width: 28px;
  height: 28px;
  fill: none;
  stroke: var(--text);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.gate__title {
  margin-top: 20px;
  font-size: clamp(1.125rem, 1.05rem + 0.3vw, 1.25rem);
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: -0.017em;
  color: var(--text-muted);
}

.gate__input,
.gate__submit {
  width: 100%;
  height: 56px;
  border-radius: 12px;
  font: inherit;
  font-size: 18px;             /* >= 16px keeps iOS from zooming on focus */
  letter-spacing: -0.2px;
}

.gate__input {
  margin-top: 32px;
  padding: 0 16px;
  border: 1px solid var(--field-border);
  background: var(--panel);
  color: var(--text);
}
.gate__input::placeholder { color: var(--text-muted); opacity: 1; }
.gate__input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.gate__input[aria-invalid="true"] { border-color: var(--danger-border); }

.gate__submit {
  margin-top: 16px;
  border: 0;
  background: var(--panel);
  color: var(--text-muted);
  cursor: pointer;
  transition: background-color .2s ease, color .2s ease;
}
.gate__submit:hover { background: var(--panel-hover); color: var(--text); }
.gate__submit:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gate__submit:disabled { cursor: progress; color: var(--text-muted); background: var(--panel); }

.gate__error {
  margin-top: 16px;
  font-size: 16px;
  line-height: 1.4;
  color: var(--danger);
}
