/* Hooshie.ai: dark, minimal, technical */

/* Palette sampled from Hooshie_logo.png:
   plate #0f111d · cyan #6ceefc · azure #59b9ec · indigo #6675d1 · violet #8b6ce8 */

:root {
  --bg: #0f111d;
  --bg-raise: #1a1e30;
  --bg-card: #141827;
  --line: rgba(150, 190, 255, 0.13);
  --line-soft: rgba(150, 190, 255, 0.07);
  --text: #eaedf6;
  --text-dim: #9aa3bd;
  --text-mute: #7a83a2; /* 5.0:1 on --bg, AA at the small sizes it's used for */
  --accent: #6ceefc;
  --accent-2: #59a9ec;
  --accent-3: #8b6ce8;
  --accent-dim: rgba(108, 238, 252, 0.13);
  --grad: linear-gradient(102deg, #6ceefc 0%, #59a9ec 46%, #8b6ce8 100%);

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --w: 1060px;
  --r: 14px;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* The header is sticky, so an anchor jump has to stop short of it or the
     target lands underneath. Header height + a little breathing room. */
  scroll-padding-top: 84px;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

a {
  color: inherit;
}

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

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

.wrap {
  width: 100%;
  max-width: var(--w);
  margin: 0 auto;
  padding: 0 28px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--accent);
  color: var(--bg);
  padding: 10px 16px;
  z-index: 50;
  font-weight: 600;
}
.skip:focus {
  left: 12px;
  top: 12px;
}

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

.site-head {
  position: sticky;
  top: 0;
  z-index: 20;
  /* --bg at 82%, written out because a colour token can't be given an alpha
     channel directly. Keep this in step with --bg if that ever changes. */
  background: rgba(15, 17, 29, 0.82);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid var(--line-soft);
}

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

.brand {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
  font-weight: 600;
  letter-spacing: 0.005em;
  font-size: 18px;
}
.brand img {
  width: auto;
  height: 34px;
  flex: none;
  /* the mark carries its own glow; nudge it optically into the row */
  margin-bottom: 2px;
}
.brand .word {
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.nav {
  display: flex;
  align-items: center;
  gap: 26px;
  font-size: 15px;
}
.nav a {
  text-decoration: none;
  color: var(--text-dim);
  transition: color 0.18s ease;
}
/* A bare 15px link is a ~20px tap target. The header is a fixed height and these
   are centred in it, so the padding buys height without moving anything.
   Excluding .btn matters: `.nav a` outranks `.btn-sm`, so an unscoped rule here
   would flatten the Contact button's own padding to zero horizontally. */
.nav a:not(.btn) {
  padding: 10px 0;
}
.nav a[aria-current="page"] {
  color: var(--text);
}
/* Every :hover in this file is guarded. On a touch screen there is no pointer
   to leave, so a tapped element keeps its hover state until you tap elsewhere,
   which reads as "stuck" rather than as feedback. */
@media (hover: hover) {
  .nav a:hover {
    color: var(--text);
  }
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 20px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 15px;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease, transform 0.18s
    ease, color 0.18s ease;
}
@media (hover: hover) {
  .btn:hover {
    background: rgba(140, 190, 255, 0.08);
    border-color: rgba(150, 200, 255, 0.28);
  }
}
/* :active is the touch equivalent, and is correct on both. */
.btn:active {
  transform: translateY(1px);
}

.btn-primary {
  background: var(--grad);
  border-color: transparent;
  color: #0b0e18;
  font-weight: 600;
  box-shadow: 0 6px 26px -10px rgba(108, 238, 252, 0.55);
}
@media (hover: hover) {
  .btn-primary:hover {
    filter: brightness(1.09);
    box-shadow: 0 8px 32px -10px rgba(108, 238, 252, 0.7);
  }
}

.btn-sm {
  padding: 8px 16px;
  font-size: 14px;
}

/* ---------- type ---------- */

.eyebrow {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-mute);
  margin: 0 0 18px;
}
.eyebrow .mark {
  color: var(--accent);
}

h1,
h2,
h3 {
  letter-spacing: -0.025em;
  line-height: 1.12;
  margin: 0;
  font-weight: 600;
}

h1 {
  font-size: clamp(2.4rem, 6.2vw, 3.9rem);
}
h2 {
  font-size: clamp(1.7rem, 3.6vw, 2.35rem);
  line-height: 1.2;
}
h3 {
  font-size: 1.16rem;
  line-height: 1.35;
}

.lede {
  font-size: clamp(1.06rem, 2vw, 1.24rem);
  color: var(--text-dim);
  max-width: 60ch;
  margin: 24px 0 0;
}

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

.hero {
  position: relative;
  padding: clamp(84px, 14vw, 156px) 0 clamp(72px, 11vw, 118px);
  overflow: hidden;
}
.hero::before {
  content: "";
  position: absolute;
  top: -300px;
  left: 50%;
  width: 1000px;
  height: 760px;
  transform: translateX(-72%);
  background: radial-gradient(
    closest-side,
    rgba(89, 169, 236, 0.16),
    transparent 70%
  );
  pointer-events: none;
}
.hero .wrap {
  position: relative;
}

/* The <picture> around the mark must not generate a box of its own: its only
   child is absolutely positioned, so as a block it is zero-height and the img
   still positions against .hero. As an inline box it would add a stray line. */
.hero picture {
  display: block;
}

/* the logo mark, echoed large and quiet behind the right edge */
.hero-mark {
  position: absolute;
  top: 50%;
  right: -110px;
  width: min(520px, 46vw);
  transform: translateY(-52%);
  opacity: 0.5;
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
  z-index: 0;
}

.hero h1,
.hero .eyebrow,
.hero .lede,
.hero-actions {
  position: relative;
  z-index: 1;
}
.hero h1 {
  max-width: 17ch;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 38px;
}

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

.section {
  padding: clamp(64px, 9vw, 104px) 0;
  border-top: 1px solid var(--line-soft);
}
.section-head {
  max-width: 62ch;
  margin-bottom: 44px;
}
.section-head p {
  color: var(--text-dim);
  margin: 16px 0 0;
}

/* Contact page: the hero runs straight into the form below it, so it drops its
   bottom padding and the following section drops its rule and some top padding.
   Both modifiers must stay *below* the .hero and .section rules they override:
   same specificity, so source order is the only thing deciding it. */
.hero--tight {
  padding-bottom: 0;
}
.section--flush {
  border-top: 0;
  padding-top: clamp(48px, 7vw, 72px);
}

/* ---------- product teaser ---------- */

.teaser {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: clamp(28px, 5vw, 46px);
  background: radial-gradient(
      120% 140% at 94% 0%,
      rgba(139, 108, 232, 0.16),
      transparent 58%
    ),
    radial-gradient(
      90% 120% at 4% 100%,
      rgba(108, 238, 252, 0.07),
      transparent 60%
    ), var(--bg-card);
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--accent-dim);
  border: 1px solid rgba(108, 238, 252, 0.3);
  border-radius: 999px;
  padding: 5px 12px;
}

.teaser h2 {
  margin: 22px 0 0;
}
.teaser p {
  color: var(--text-dim);
  max-width: 58ch;
  margin: 18px 0 0;
  font-size: 1.05rem;
}

.teaser-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 22px;
  margin-top: 30px;
  padding-top: 26px;
  border-top: 1px solid var(--line-soft);
  font-family: var(--mono);
  font-size: 13px;
  color: var(--text-mute);
}
.teaser-meta strong {
  color: var(--text);
  font-weight: 500;
}

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

.grid {
  display: grid;
  gap: 18px;
  grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
}

.card {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--bg-card);
  padding: 30px 28px 32px;
  overflow: hidden;
  transition: border-color 0.2s ease, background 0.2s ease, transform 0.2s ease;
}
/* gradient hairline along the top edge, revealed on hover */
.card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: var(--grad);
  opacity: 0;
  transition: opacity 0.22s ease;
}
/* Cards aren't links, so on touch a latched hover is pure noise: the card lifts
   and stays lifted after an incidental tap, suggesting it did something. */
@media (hover: hover) {
  .card:hover {
    border-color: rgba(150, 200, 255, 0.26);
    background: var(--bg-raise);
    transform: translateY(-2px);
  }
  .card:hover::before {
    opacity: 1;
  }
}
.card .num {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--accent);
  letter-spacing: 0.1em;
}
.card h3 {
  margin: 16px 0 12px;
}
.card p {
  margin: 0;
  color: var(--text-dim);
  font-size: 15.5px;
  line-height: 1.62;
}

/* ---------- principles ---------- */

.principles {
  display: grid;
  gap: 0;
  /* Exactly three items, so auto-fit's intermediate two-column step always left
     a ragged half-empty row. It goes three across or one down, nothing between. */
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
}
/* Dividers as box-shadow, not border. A shadow paints outside the element, so
   the ones on the outermost items land exactly on the container's own border
   and are clipped away by its overflow:hidden. Borders can't do that: they
   paint inside, so the right-hand column drew a stray hairline over the
   container edge and every item's bottom border doubled the container's.
   Which items are outermost changes with the column count, and :last-child
   only ever knew about one of them. */
.principles > div {
  padding: 28px;
  box-shadow: 1px 0 0 var(--line-soft), 0 1px 0 var(--line-soft);
}
.principles h3 {
  font-size: 1rem;
  margin: 0 0 10px;
}
.principles p {
  margin: 0;
  color: var(--text-dim);
  font-size: 15px;
}

/* ---------- cta band ---------- */

.cta {
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: clamp(34px, 6vw, 56px);
  text-align: center;
  background: radial-gradient(
      90% 160% at 50% 0%,
      rgba(89, 169, 236, 0.14),
      transparent 62%
    ), var(--bg-card);
}
.cta p {
  color: var(--text-dim);
  margin: 16px auto 30px;
  max-width: 48ch;
}

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

.contact-layout {
  display: grid;
  gap: 46px;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.85fr);
  align-items: start;
}

.field {
  margin-bottom: 20px;
}
.field label {
  display: block;
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 8px;
  color: var(--text);
}
.field .hint {
  color: var(--text-mute);
  font-weight: 400;
}

input,
textarea {
  width: 100%;
  font: inherit;
  font-size: 16px;
  color: var(--text);
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px 14px;
  transition: border-color 0.18s ease, background 0.18s ease;
}
input::placeholder,
textarea::placeholder {
  color: var(--text-mute);
}
input:focus,
textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--bg-raise);
}
/* Set by the form's validation. Without this the flag is real to a screen
   reader and invisible to everyone else. */
input[aria-invalid="true"],
textarea[aria-invalid="true"] {
  border-color: rgba(236, 106, 122, 0.75);
}
textarea {
  resize: vertical;
  min-height: 148px;
  line-height: 1.6;
}

.captcha label {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.captcha label > span[data-captcha-a],
.captcha label > span[data-captcha-b] {
  font-family: var(--mono);
  color: var(--accent);
  font-size: 15px;
}
.captcha .hint {
  font-size: 13px;
  font-style: italic;
}
.captcha input {
  max-width: 190px;
}

.form-note {
  font-size: 13.5px;
  color: var(--text-mute);
  margin: 18px 0 0;
}

/* Never display:none. This is the form's aria-live region: a region that only
   enters the accessibility tree at the moment it gets its first message is
   often not announced at all. Empty, it has no text, padding or margin, so it
   takes up no space while staying in the tree. */
.form-status {
  border-radius: 10px;
  font-size: 15px;
}
.form-status.show {
  margin-top: 18px;
  padding: 13px 16px;
}
.form-status.ok {
  background: rgba(108, 238, 252, 0.11);
  border: 1px solid rgba(108, 238, 252, 0.38);
  color: #a8e9f5;
}
.form-status.err {
  background: rgba(236, 106, 122, 0.12);
  border: 1px solid rgba(236, 106, 122, 0.42);
  color: #f0a3ad;
}

.hp {
  position: absolute;
  left: -9999px;
  opacity: 0;
}

.aside-block {
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--bg-card);
  padding: 28px;
}
.aside-block + .aside-block {
  margin-top: 18px;
}
.aside-block h3 {
  font-size: 1rem;
  margin: 0 0 14px;
}
.aside-block p {
  margin: 0 0 14px;
  color: var(--text-dim);
  font-size: 15px;
}
.aside-block p:last-child {
  margin-bottom: 0;
}

.link-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 0;
  border-top: 1px solid var(--line-soft);
  text-decoration: none;
  color: var(--text);
  font-size: 15px;
  transition: color 0.18s ease;
}
.link-row:first-of-type {
  border-top: 0;
  padding-top: 0;
}
.link-row svg {
  width: 17px;
  height: 17px;
  flex: none;
  color: var(--text-mute);
}
@media (hover: hover) {
  .link-row:hover,
  .link-row:hover svg {
    color: var(--accent);
  }
}

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

.site-foot {
  border-top: 1px solid var(--line-soft);
  padding: 40px 0 56px;
  color: var(--text-mute);
  font-size: 14.5px;
}
/* One line of text, so no layout of its own. The flex row, the link colours and
   the .foot-links block all went with the footer nav they existed for. */

/* ---------- responsive ---------- */

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

@media (max-width: 780px) {
  /* Three 240px columns no longer fit. Straight to one. */
  .principles {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 760px) {
  .hero-mark {
    right: -22%;
    width: 78vw;
    opacity: 0.26;
  }
}

@media (max-width: 600px) {
  html {
    scroll-padding-top: 78px;
  }
  body {
    font-size: 16px;
  }
  .wrap {
    padding: 0 20px;
  }
  .site-head .wrap {
    height: 62px;
  }
  /* backdrop-filter on a sticky element re-blurs everything beneath it on every
     scroll frame, which is where mid-range phones drop frames. At 94% opacity
     the blur has almost nothing left to contribute, so trade it for the frames. */
  .site-head {
    background: rgba(15, 17, 29, 0.94);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .nav {
    gap: 16px;
    font-size: 14.5px;
  }
  .brand {
    font-size: 17px;
    gap: 9px;
  }
  .brand img {
    height: 29px;
  }
  .hero-actions .btn {
    flex: 1 1 auto;
  }
}

/* Declared after the responsive block on purpose: the contact page's mark keeps
   its own smaller sizing at every width, because the .hero-mark phone rule above
   is tuned for the home page's much larger echo. Previously these three values
   were inline styles on the element, which won for the same reason but silently,
   and would have kept winning over any later rule anyone added. */
.hero-mark--soft {
  right: -40px;
  width: min(340px, 34vw);
  opacity: 0.34;
}
@media (max-width: 600px) {
  .hero-mark--soft {
    right: -30px;
    opacity: 0.26;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
