/* ==========================================================================
   LightsOutGP
   Token order follows the brief (section 3). Do not add colours to this list
   without checking section 3 first — red is deliberately constrained.
   ========================================================================== */

:root {
  --ink: #1D1D1B;
  --signal: #E6333F;
  --signal-ink: #C41F2B;
  --paper: #FFFFFF;
  --mist: #F5F4F2;
  --line: #E4E2DF;
  --muted: #6E6E6B;

  --shadow-rest: 0 1px 2px rgb(0 0 0 / 0.04);
  --shadow-hover: 0 12px 32px rgb(0 0 0 / 0.08);

  --radius-card: 16px;
  --radius-input: 10px;
  --radius-pill: 999px;

  --content: 1200px;
  --gutter: 24px;
  --section-y: 112px;
  --header-h: 80px;
  --header-h-shrunk: 64px;

  --font-display: 'Figtree', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-body: 'Instrument Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
}

@media (min-width: 768px) {
  :root { --gutter: 48px; }
}

@media (max-width: 767px) {
  :root { --section-y: 72px; }
}

/* --- Fonts ---------------------------------------------------------------
   Self-hosted, subset to Latin, two weights per family (brief: performance).
   Display face is Figtree, not Archivo: the lightoutgp.svg wordmark reads
   geometric, and the brief says to swap in that case (section 3).
   ------------------------------------------------------------------------ */

@font-face {
  font-family: 'Figtree';
  src: url('../fonts/figtree-600.woff2') format('woff2');
  font-weight: 600;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+20AC, U+2122;
}

@font-face {
  font-family: 'Figtree';
  src: url('../fonts/figtree-700.woff2') format('woff2');
  font-weight: 700;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+20AC, U+2122;
}

@font-face {
  font-family: 'Instrument Sans';
  src: url('../fonts/instrument-sans-400.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+20AC, U+2122;
}

@font-face {
  font-family: 'Instrument Sans';
  src: url('../fonts/instrument-sans-500.woff2') format('woff2');
  font-weight: 500;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+20AC, U+2122;
}

/* --- Reset --------------------------------------------------------------- */

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

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

/* The page must never scroll horizontally at any breakpoint (acceptance
   criterion). Individual wide things (dest grid, trust bar) scroll inside
   their own containers instead. */
html, body { overflow-x: clip; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 17px;
  font-weight: 400;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

@media (max-width: 767px) {
  body { font-size: 16px; }
}

img, picture, svg, video { display: block; max-width: 100%; }
img { height: auto; }

/* A `display` rule beats the [hidden] UA default, which silently breaks the
   tabpanels. Make [hidden] win everywhere except the FAQ panels, which stay
   in the box tree while their height animates. */
[hidden]:not(.faq__panel) { display: none !important; }

button, input, select, textarea {
  font: inherit;
  color: inherit;
}

h1, h2, h3, p, ul, ol, figure, blockquote { margin: 0; }
ul, ol { padding: 0; list-style: none; }

/* --- Focus --------------------------------------------------------------
   Brief treats this as an acceptance criterion: never remove outlines.
   ------------------------------------------------------------------------ */

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

/* Dark surfaces need a light ring to stay visible. */
.footer :focus-visible,
.hero :focus-visible {
  outline-color: var(--paper);
}

/* --- Typography ---------------------------------------------------------- */

h1, h2, h3, .display {
  font-family: var(--font-display);
  color: var(--ink);
  text-wrap: balance;
}

h1 {
  font-size: 56px;
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.02em;
}

h2 {
  font-size: 40px;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
}

h3 {
  font-size: 22px;
  font-weight: 600;
  line-height: 1.3;
}

@media (max-width: 767px) {
  h1 { font-size: 36px; }
  h2 { font-size: 28px; }
  h3 { font-size: 20px; }
}

.label {
  font-size: 13px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}

.muted { color: var(--muted); }

/* Brief: body copy max 68ch, never full-bleed text. */
.prose { max-width: 68ch; }
.prose p + p { margin-top: 1.1em; }

.footnote {
  font-size: 13px;
  color: var(--muted);
}

/* --- Layout -------------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--content);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

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

.section--mist { background: var(--mist); }
.section--paper { background: var(--paper); }

/* Anchors must not land under the sticky header. */
[id] { scroll-margin-top: calc(var(--header-h) + 16px); }

.section__head {
  max-width: 720px;
  margin-bottom: 56px;
}

.section__head--center {
  margin-inline: auto;
  text-align: center;
}

.section__intro {
  margin-top: 16px;
  color: var(--muted);
  max-width: 60ch;
}

.section__head--center .section__intro { margin-inline: auto; }

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

.skip-link {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -120%);
  z-index: 200;
  padding: 12px 20px;
  background: var(--paper);
  color: var(--ink);
  font-weight: 500;
  border-radius: 0 0 var(--radius-input) var(--radius-input);
  box-shadow: var(--shadow-hover);
  transition: transform 150ms ease;
}

.skip-link:focus { transform: translate(-50%, 0); }

/* --- Buttons ------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 24px;
  border: 0;
  border-radius: var(--radius-input);
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 500;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 150ms ease, color 150ms ease;
}

.btn--primary {
  background: var(--signal);
  color: var(--paper);
}

.btn--primary:hover { background: var(--signal-ink); }

.btn--primary:disabled {
  background: var(--muted);
  cursor: not-allowed;
}

.btn--sm { padding: 10px 18px; font-size: 15px; }

.btn--block { width: 100%; }

.link-quiet {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  transition: text-decoration-color 150ms ease;
}

.link-quiet:hover { text-decoration-color: var(--signal); }

/* --- The lights ---------------------------------------------------------
   Signature element (brief section 3). Five circles, 14px, 20px apart.
   ------------------------------------------------------------------------ */

.lights {
  display: flex;
  gap: 20px;
  align-items: center;
  /* The row is the hover target, not each dot, so the 20px gaps stay live and
     the lights do not flicker as the pointer crosses them. width:max-content
     keeps that target tight to the dots instead of spanning the whole column,
     which would light the row from anywhere on the hero. Padding grows the
     target vertically; no negative margin, so it cannot overlap the H1 below
     and swallow its pointer events. */
  width: max-content;
  padding: 8px 4px;
}

/* Lighting up on hover must feel immediate; extinguishing can trail slightly,
   which reads as a lamp cooling rather than a switch flicking. */
.lights__dot {
  transition: background-color 90ms ease-out, box-shadow 220ms ease-out,
    border-color 90ms ease-out;
}

.lights__dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--line);
  flex: none;
  /* The hero variant adds a 1px rim; border-box keeps the dot at the 14px the
     brief specifies rather than growing to 16px. */
  box-sizing: border-box;
  border: 1px solid transparent;
}

.lights__dot--lit {
  background: var(--signal);
  box-shadow: 0 0 12px rgb(230 51 63 / 0.6);
}

/* On the hero the dots sit on a photograph and must read as an unlit gantry
   light, not as carousel controls. A dark recessed well with a hairline rim and
   a small specular highlight does that: it looks like a lamp that is off.
   Without this the resting state (which is what returning visitors see, since
   the sequence runs once per session) invites a click. */
.hero .lights__dot {
  background: radial-gradient(
    circle at 50% 34%,
    rgb(255 255 255 / 0.20) 0%,
    rgb(255 255 255 / 0.05) 45%,
    rgb(0 0 0 / 0.35) 100%
  );
  border: 1px solid rgb(255 255 255 / 0.30);
  box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.5);
}

.hero .lights__dot--lit {
  background: var(--signal);
  border-color: rgb(255 255 255 / 0.5);
  box-shadow:
    0 0 18px rgb(230 51 63 / 0.85),
    inset 0 1px 2px rgb(255 255 255 / 0.35);
}

/* The five-dot section divider from the brief is deliberately not implemented.
   Unlit dots between sections read as broken carousel controls. Alternating
   --paper / --mist backgrounds already separate the sections. */

/* --- Header -------------------------------------------------------------- */

.header {
  position: sticky;
  top: 0;
  z-index: 100;
  height: var(--header-h);
  display: flex;
  align-items: center;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: height 200ms ease, background-color 200ms ease, border-color 200ms ease;
}

.header.is-scrolled {
  height: var(--header-h-shrunk);
  background: var(--paper);
  border-bottom-color: var(--line);
}

.header__inner {
  display: flex;
  align-items: center;
  gap: 32px;
  width: 100%;
  max-width: var(--content);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.header__logo { flex: none; }

.header__logo img {
  width: 148px;
  height: auto;
  transition: width 200ms ease;
}

.header.is-scrolled .header__logo img { width: 132px; }

/* The hero is a photograph, so before scroll the header sits on dark pixels
   and needs the white logo. After scroll the bar is --paper: use the colour one. */
.header__logo .logo--light { display: block; }
.header__logo .logo--dark { display: none; }
.header.is-scrolled .logo--light { display: none; }
.header.is-scrolled .logo--dark { display: block; }

.header__nav {
  display: flex;
  gap: 28px;
  margin-left: auto;
}

.header__nav a {
  color: var(--paper);
  text-decoration: none;
  font-size: 16px;
  padding-block: 4px;
  border-bottom: 2px solid transparent;
  transition: border-color 150ms ease;
}

.header.is-scrolled .header__nav a { color: var(--ink); }

.header__nav a:hover { border-bottom-color: var(--signal); }

.header__cta { flex: none; }

.header__burger {
  display: none;
  flex: none;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--paper);
}

.header.is-scrolled .header__burger { color: var(--ink); }

@media (max-width: 899px) {
  .header__nav { display: none; }
  .header__burger { display: flex; margin-left: auto; }
  .header__inner { gap: 12px; }
  .header__logo img { width: 124px; }
}

/* At the narrowest supported width the three header items do not fit at full
   size. The CTA is the one thing that must never disappear, so the logo and
   the gutters give way instead of the button. */
@media (max-width: 420px) {
  .header__inner {
    gap: 8px;
    padding-inline: 16px;
  }
  .header__logo img { width: 96px; }
  .header.is-scrolled .header__logo img { width: 96px; }
  .header__burger { width: 40px; }
  .header__cta .btn {
    padding: 10px 12px;
    font-size: 14px;
    white-space: nowrap;
  }
}

/* --- Drawer -------------------------------------------------------------- */

.drawer {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: none;
}

.drawer[data-open='true'] { display: block; }

.drawer__scrim {
  position: absolute;
  inset: 0;
  background: rgb(29 29 27 / 0.5);
  border: 0;
  width: 100%;
  cursor: pointer;
}

.drawer__panel {
  position: absolute;
  inset-block: 0;
  right: 0;
  width: min(360px, 88vw);
  background: var(--paper);
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow-y: auto;
}

.drawer__close {
  align-self: flex-end;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  cursor: pointer;
  margin-bottom: 8px;
}

.drawer__panel a {
  color: var(--ink);
  text-decoration: none;
  font-size: 18px;
  padding: 14px 8px;
  border-bottom: 1px solid var(--line);
}

/* --- Hero ---------------------------------------------------------------- */

.hero {
  position: relative;
  min-height: 640px;
  display: flex;
  align-items: center;
  /* Pull the header up over the photograph. */
  margin-top: calc(var(--header-h) * -1);
  padding-top: var(--header-h);
  isolation: isolate;
  /* The photograph must stop at the hero's own bottom edge. Without this the
     media layer paints behind the following (transparent) planner strip and
     bleeds into the trust bar. */
  overflow: hidden;
}

@media (max-width: 767px) {
  .hero { min-height: 520px; }
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
  /* Also constrains the placeholder box when no photograph is supplied yet. */
  overflow: hidden;
}

.hero__media .todo-media {
  height: 100%;
  aspect-ratio: auto !important;
}

/* The <picture> wrapper is a plain inline element by default, so height:100% on
   the <img> resolves against nothing and the photo collapses to its intrinsic
   ratio instead of covering the hero. Both need to fill. */
.hero__media picture {
  display: block;
  width: 100%;
  height: 100%;
}

.hero__media img {
  width: 100%;
  height: 100%;
  /* Beats `img { height: auto }` in the reset, which otherwise wins here and
     leaves the photo only as tall as its aspect ratio allows. */
  min-height: 100%;
  object-fit: cover;
  /* Keep the text side of the frame calm. */
  object-position: 60% center;
}

/* The brief specifies this gradient, and its shape is kept: strong at the left
   where the text sits, clearing to nothing by 60% so the photograph is still
   the subject. The opacities are raised from the brief's starting values
   because measuring white text against the LIGHTEST pixel of this particular
   photograph gave 3.05:1 at the brief's numbers, and the acceptance criterion
   is >= 4.5:1. Re-measure if the hero photograph is replaced:
   npm run check reports it. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    90deg,
    rgb(29 29 27 / 0.82) 0%,
    rgb(29 29 27 / 0.78) 55%,
    rgb(29 29 27 / 0.30) 82%,
    transparent 100%
  );
}

/* A gentle vertical wash evens out bright patches in the upper half without
   turning the hero into a flat dark rectangle. */
.hero__scrim::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgb(29 29 27 / 0.30) 0%,
    rgb(29 29 27 / 0.34) 100%
  );
}

.hero__inner {
  position: relative;
  width: 100%;
  max-width: var(--content);
  margin-inline: auto;
  /* Top padding clears the sticky header, which the hero is pulled up under.
     Bottom padding leaves room for the planner bar to sit on the hero's lower
     edge without covering the subheading. */
  padding: 72px var(--gutter) 104px;
}

@media (max-width: 899px) {
  .hero__inner { padding-block: 64px 72px; }
}

.hero__text { max-width: 640px; }

.hero h1 {
  color: var(--paper);
  /* 28px from the brief, less the .lights hover padding above. */
  margin-top: 20px;
}

.hero__sub {
  color: var(--paper);
  margin-top: 20px;
  max-width: 52ch;
  font-size: 19px;
}

@media (max-width: 767px) {
  .hero__sub { font-size: 17px; }
}

/* Under reduced motion, or with JS off, content must be visible. The lights
   script adds .is-ready once it has taken over. */
.hero__reveal { opacity: 1; }

.js .hero .hero__reveal {
  opacity: 0;
  transform: translateY(12px);
}

.js .hero.is-revealed .hero__reveal {
  opacity: 1;
  transform: none;
  transition: opacity 400ms ease, transform 400ms ease;
}

/* This link lives below the planner bar, on --paper, not on the photograph,
   so it takes ink rather than white. */
.hero__after {
  margin-top: 24px;
}

.hero__after a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-color: var(--line);
}

.hero__after a:hover { text-decoration-color: var(--signal); }

/* --- Planner bar --------------------------------------------------------- */

.planner {
  position: relative;
  z-index: 2;
  margin-top: -40px;
  background: var(--paper);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-rest);
  display: grid;
  grid-template-columns: 1fr 1fr 1fr auto;
  align-items: stretch;
  overflow: hidden;
}

.planner__field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 18px 20px;
  border-right: 1px solid var(--line);
  min-width: 0;
}

.planner__field select {
  border: 0;
  background: none;
  padding: 0;
  font-size: 16px;
  width: 100%;
  cursor: pointer;
}

.planner__submit {
  display: flex;
  align-items: center;
  padding: 14px;
}

.planner__submit .btn { height: 100%; }

@media (max-width: 899px) {
  /* Brief: on mobile the bar sits below the hero, does not overlap it,
     and the button is full width. */
  .planner {
    grid-template-columns: 1fr;
    margin-top: 24px;
  }
  .planner__field {
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }
  /* Brief: the button is full width on mobile. Match the fields' 20px
     horizontal padding so its edges line up with the labels above. */
  .planner__submit { padding: 16px 20px 20px; }
  .planner__submit .btn { width: 100%; }
}

/* The hero clips its own photograph, so nothing can bleed into the trust bar.
   The shell itself stays --paper and in flow; only the card is lifted (see
   .planner margin-top below), which is what produces the 40px overlap. */
.planner-shell {
  position: relative;
  z-index: 3;
  background: var(--paper);
  padding-bottom: 40px;
}

.planner-shell .hero__after { margin-top: 20px; }

@media (max-width: 899px) {
  /* Below 900px the bar sits below the hero rather than overlapping it. */
  .planner-shell {
    margin-top: 0;
    padding-bottom: 32px;
  }
}

/* --- Trust bar ----------------------------------------------------------- */

.trust {
  background: var(--mist);
  padding-block: 56px;
}

.trust__list {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 24px;
}

.trust__item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.45;
}

/* 26px icons: optically centred against the first line of text rather than
   top-aligned, which left them sitting high. */
.trust__item svg { flex: none; margin-top: -1px; color: var(--signal); }

/* The brief made this a hidden-scrollbar horizontal strip below 900px. Replaced
   with a wrapping grid: a scroller with no visible scrollbar hides content, and
   these five claims are the page's trust signals — the least appropriate thing
   on the page to make people discover by swiping. */
@media (max-width: 899px) {
  .trust__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* Five items over two columns leaves the last one alone on its row; letting
     it span both keeps the block from looking truncated. */
  .trust__item:last-child { grid-column: 1 / -1; }
}

@media (max-width: 479px) {
  /* At phone widths two columns squeeze these to two or three words per line. */
  .trust__list { grid-template-columns: 1fr; }
  .trust__item:last-child { grid-column: auto; }
}

/* --- Cards --------------------------------------------------------------- */

.cards {
  display: grid;
  gap: 32px;
}

.cards--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

@media (max-width: 899px) {
  .cards--2 { grid-template-columns: 1fr; }
}

.card {
  background: var(--paper);
  border-radius: var(--radius-card);
}

.card__media {
  border-radius: var(--radius-card);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--mist);
}

.card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card h3 { margin-top: 24px; }

.card p { margin-top: 12px; color: var(--muted); }

.ticks {
  margin-top: 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.ticks li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 16px;
}

.ticks svg { flex: none; margin-top: 5px; color: var(--signal); }

/* --- Steps --------------------------------------------------------------- */

.steps {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 32px;
  position: relative;
}

/* The hairline runs behind the numbers. */
.steps::before {
  content: '';
  position: absolute;
  top: 22px;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--line);
}

.step { position: relative; }

.step__num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 32px;
  line-height: 1;
  color: var(--signal);
  background: var(--mist);
  padding-right: 16px;
  display: inline-block;
  position: relative;
}

.step h3 { margin-top: 20px; }
.step p { margin-top: 10px; color: var(--muted); }

@media (max-width: 899px) {
  .steps {
    grid-template-columns: 1fr;
    gap: 36px;
    padding-left: 28px;
  }
  .steps::before {
    top: 0;
    bottom: 0;
    left: 0;
    right: auto;
    width: 1px;
    height: auto;
  }
  .step__num {
    background: var(--mist);
    padding: 0 12px 0 0;
    margin-left: -28px;
  }
}

.steps__closing {
  margin-top: 56px;
  text-align: center;
  color: var(--muted);
}

/* --- Levels -------------------------------------------------------------
   Brief: three columns of equal weight. Do not promote the middle one.
   ------------------------------------------------------------------------ */

.levels {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 32px;
}

@media (max-width: 899px) {
  .levels { grid-template-columns: 1fr; }
}

.level {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 32px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
}

.level__price {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 24px;
  color: var(--ink);
}

.level p { color: var(--muted); }

.level .ticks { margin-top: 4px; }

.level__link { margin-top: auto; padding-top: 12px; }

.level__link a {
  color: var(--ink);
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-underline-offset: 4px;
}

.level__link a:hover { text-decoration-color: var(--signal); }

/* --- Destinations -------------------------------------------------------- */

.tabs {
  display: flex;
  gap: 12px;
  margin-bottom: 40px;
}

.tab {
  padding: 10px 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--paper);
  color: var(--ink);
  font-size: 15px;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 150ms ease, color 150ms ease, border-color 150ms ease;
}

.tab[aria-selected='true'] {
  background: var(--signal);
  border-color: var(--signal);
  color: var(--paper);
}

.dests {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 24px;
}

@media (max-width: 1023px) {
  .dests { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.dest {
  display: block;
  width: 100%;
  /* A <button> sizes to its intrinsic content and will not shrink below it,
     which blows out the grid. min-width:0 lets the grid track win. */
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
  border-radius: var(--radius-card);
  transition: transform 150ms ease, box-shadow 150ms ease;
}

.dest__media,
.dest__body { display: block; }

.dest__title { overflow-wrap: break-word; }

.dest:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-hover);
}

.dest__media {
  border-radius: var(--radius-card);
  overflow: hidden;
  aspect-ratio: 3 / 2;
  background: var(--line);
}

.dest__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 300ms ease;
}

.dest__title {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 20px;
  line-height: 1.3;
}

.dest:hover .dest__media img { transform: scale(1.03); }

.dest__body { padding: 16px 4px 4px; }

.dest__meta {
  margin-top: 4px;
  color: var(--muted);
  font-size: 15px;
}

@media (max-width: 767px) {
  /* Brief: one and a half cards peeking on a horizontal scroll.
     The row bleeds to the screen edge so the next card can peek, but the
     padding puts the FIRST card on the same gutter as every other section, so
     it lines up with the heading above it instead of touching the edge. */
  .dests {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    gap: 16px;
  }
  .dests::-webkit-scrollbar { display: none; }
  .dest {
    flex: none;
    width: 66vw;
    /* Snap accounts for the padding, so a snapped card sits on the gutter
       rather than under it. */
    scroll-snap-align: start;
    scroll-margin-left: var(--gutter);
  }
}

/* --- About --------------------------------------------------------------- */

.about {
  display: grid;
  grid-template-columns: 5fr 7fr;
  gap: 64px;
  align-items: start;
}

@media (max-width: 899px) {
  .about { grid-template-columns: 1fr; gap: 32px; }
}

/* No team photograph: one centred column. Text stays left-aligned inside it,
   because centred body copy at this length is hard to read — only the column
   itself is centred on the page. */
.about--centred {
  display: block;
  max-width: 760px;
  margin-inline: auto;
  text-align: center;
}

.about--centred .about__prose {
  margin-top: 24px;
  color: var(--muted);
  text-align: left;
}

.about--centred .about__prose p + p { margin-top: 1.1em; }

.about__media {
  border-radius: var(--radius-card);
  overflow: hidden;
  aspect-ratio: 4 / 5;
  background: var(--mist);
}

.about__media img { width: 100%; height: 100%; object-fit: cover; }

.stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 24px;
  margin-top: 48px;
  text-align: center;
}

@media (max-width: 599px) {
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.stat__num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 32px;
  line-height: 1.1;
  color: var(--ink);
  /* One of these is a phrase ("Under 24 h"), not a numeral, so it must be
     allowed to wrap without pushing the tile wider than its track. */
  text-wrap: balance;
  overflow-wrap: break-word;
}

.stat__label {
  margin-top: 8px;
  font-size: 13px;
  color: var(--muted);
  line-height: 1.4;
  /* Spreads the label evenly over its lines instead of leaving a single
     orphaned word ("...has worked / at") on the last one. */
  text-wrap: pretty;
  max-width: 22ch;
  margin-inline: auto;
}

/* --- FAQ ----------------------------------------------------------------- */

.faq {
  max-width: 800px;
  margin-inline: auto;
}

.faq__item { border-bottom: 1px solid var(--line); }

.faq__trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 24px 4px;
  background: none;
  border: 0;
  text-align: left;
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
}

.faq__chevron {
  flex: none;
  color: var(--muted);
  transition: transform 200ms ease;
}

.faq__trigger[aria-expanded='true'] .faq__chevron { transform: rotate(180deg); }

.faq__panel {
  overflow: hidden;
  height: 0;
  transition: height 250ms ease;
}

.faq__panel[hidden] {
  display: block;
  height: 0;
}

.faq__panel-inner {
  padding: 0 4px 24px;
  color: var(--muted);
  max-width: 68ch;
}

/* Brief: all panels open when printed. */
@media print {
  .faq__panel, .faq__panel[hidden] { height: auto !important; display: block !important; }
}

/* --- Enquiry form -------------------------------------------------------- */

.enquiry {
  display: grid;
  grid-template-columns: 6fr 4fr;
  gap: 64px;
  align-items: start;
}

@media (max-width: 899px) {
  .enquiry { grid-template-columns: 1fr; gap: 40px; }
  /* Brief: reassurance panel moves above the form. */
  .enquiry__aside { order: -1; }
}

.reassure {
  background: var(--mist);
  border-radius: var(--radius-card);
  padding: 32px;
}

@media (min-width: 900px) {
  .reassure { position: sticky; top: calc(var(--header-h) + 32px); }
}

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

.reassure li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.reassure svg { flex: none; margin-top: 5px; color: var(--signal); }

.form__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
}

@media (max-width: 599px) {
  .form__grid { grid-template-columns: 1fr; }
}

.field { display: flex; flex-direction: column; gap: 8px; }
.field--full { grid-column: 1 / -1; }

.field label {
  font-size: 13px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}

.field .req { color: var(--signal); }

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 13px 14px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-input);
  font-size: 16px;
  transition: border-color 150ms ease;
}

.field textarea { resize: vertical; min-height: 108px; }

.field input:hover,
.field select:hover,
.field textarea:hover { border-color: var(--muted); }

.field__error {
  font-size: 13px;
  color: var(--signal);
  min-height: 0;
}

/* Never colour alone: the error text above always accompanies this. */
.field[data-invalid='true'] input,
.field[data-invalid='true'] select,
.field[data-invalid='true'] textarea {
  border-color: var(--signal);
}

.field--phone { display: flex; flex-direction: column; gap: 8px; }

.field--phone .phone-row {
  display: grid;
  grid-template-columns: 116px 1fr;
  gap: 8px;
}

.check {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 12px;
  align-items: start;
}

.check input {
  width: 20px;
  height: 20px;
  margin: 2px 0 0;
  accent-color: var(--signal);
  flex: none;
}

.check label {
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink);
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
}

.check a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }

/* Honeypot: off-screen, not display:none (brief section 9). */
.honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form__foot {
  margin-top: 32px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  align-items: flex-start;
}

@media (max-width: 599px) {
  .form__foot .btn { width: 100%; }
}

.form__status {
  font-size: 15px;
  color: var(--signal);
}

.spinner {
  width: 16px;
  height: 16px;
  border: 2px solid rgb(255 255 255 / 0.4);
  border-top-color: var(--paper);
  border-radius: 50%;
  animation: spin 700ms linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

.form__success {
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 40px;
}

.form__success h3 { color: var(--ink); }

/* --- Contact ------------------------------------------------------------- */

.contact {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 40px;
}

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

.contact__block p { margin-top: 8px; }
.contact__block a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }

/* --- Footer -------------------------------------------------------------- */

.footer {
  background: var(--ink);
  color: rgb(255 255 255 / 0.8);
  padding-block: 64px 48px;
  font-size: 15px;
}

.footer a {
  color: rgb(255 255 255 / 0.8);
  text-decoration: none;
}

.footer a:hover { color: var(--paper); text-decoration: underline; text-underline-offset: 3px; }

.footer__top {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 48px;
  padding-bottom: 40px;
  border-bottom: 1px solid rgb(255 255 255 / 0.12);
}

@media (max-width: 899px) {
  .footer__top { grid-template-columns: 1fr; gap: 32px; }
}

.footer__logo img { width: 160px; }

.footer__links {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 32px;
}

.footer__links ul { display: flex; flex-direction: column; gap: 10px; }

.footer__legal {
  padding-block: 32px;
  border-bottom: 1px solid rgb(255 255 255 / 0.12);
  font-size: 13px;
  color: rgb(255 255 255 / 0.6);
  line-height: 1.7;
}

.footer__bottom {
  padding-top: 32px;
  font-size: 13px;
  color: rgb(255 255 255 / 0.6);
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.footer__disclaimer { max-width: 80ch; }

/* --- Placeholder guard --------------------------------------------------
   Staging only. The production build refuses to emit these — see
   scripts/build.mjs. They must be impossible to ship unnoticed.
   ------------------------------------------------------------------------ */

.todo {
  display: inline-block;
  padding: 1px 8px;
  border: 2px solid var(--signal);
  border-radius: 4px;
  background: rgb(230 51 63 / 0.08);
  color: var(--signal);
  font-family: ui-monospace, monospace;
  font-size: 0.85em;
  font-weight: 600;
  white-space: nowrap;
}

.footer .todo { color: #ff8b93; border-color: #ff8b93; }

/* Draft legal text awaiting the lawyer's sign-off. Same guarantee as .todo:
   the production build refuses to emit it. Deliberately loud, and placed above
   the body rather than beside it, so a reviewer cannot mistake a draft for
   approved wording. */
.legal-draft {
  margin: 24px 0 40px;
  padding: 20px 22px;
  border: 2px solid var(--signal);
  border-radius: 10px;
  background: rgb(230 51 63 / 0.06);
}

.legal-draft p {
  margin: 0;
  font-size: 15px;
  line-height: 1.55;
}

.legal-draft p + p { margin-top: 10px; }

.legal-draft strong { color: var(--signal); }

.legal-draft code,
.legal-draft__mark {
  font-family: ui-monospace, monospace;
  font-size: 0.9em;
}

.legal-draft__mark { color: var(--signal); font-weight: 600; }

.todo-media {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  background: repeating-linear-gradient(
    45deg,
    var(--mist) 0 12px,
    #ebe9e6 12px 24px
  );
  color: var(--muted);
  font-family: ui-monospace, monospace;
  font-size: 13px;
  text-align: center;
  padding: 16px;
}

/* --- Scroll reveal ------------------------------------------------------
   Brief: sections fade up 12px over 400ms, staggered 60ms in grids.
   No-JS and reduced-motion must both render final state.
   ------------------------------------------------------------------------ */

.js .reveal {
  opacity: 0;
  transform: translateY(12px);
}

.js .reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity 400ms ease, transform 400ms ease;
  transition-delay: var(--reveal-delay, 0ms);
}

/* --- Reduced motion ----------------------------------------------------
   Brief: nothing animates, content renders in final state immediately,
   lights render as five unlit dots.
   ------------------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  .js .reveal,
  .js .hero .hero__reveal {
    opacity: 1 !important;
    transform: none !important;
  }

  /* Lights render statically as five unlit dots. */
  .lights__dot--lit {
    background: var(--line);
    box-shadow: none;
  }

  .hero .lights__dot--lit {
    background: radial-gradient(
      circle at 50% 34%,
      rgb(255 255 255 / 0.20) 0%,
      rgb(255 255 255 / 0.05) 45%,
      rgb(0 0 0 / 0.35) 100%
    );
    border-color: rgb(255 255 255 / 0.30);
    box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.5);
  }

  .dest:hover .dest__media img { transform: none; }
}
