﻿/* Seity Sound — single page, plain white, monospace */

:root {
  --ink: #111111;
  --ink-soft: #5a5a5a;
  --rule: #e2e2e2;
  --accent: #1a1a1a;
  /* Whatever monospace the visitor's platform already has — nothing is
     downloaded. Apple resolves to SF Mono, Windows to Consolas, Linux to
     Liberation Mono, Android falls through the generic to Roboto Mono. */
  --font: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas,
          'Liberation Mono', 'Courier New', monospace;

  /* Set by script.js — a sensible default so the page still reads with JS off */
  --frame-h: 380px;
}

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

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

body {
  margin: 0;
  background: #ffffff;
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.65;
  overflow-x: hidden;
}

/* In a monospace face 1ch is exactly one character, so this really is a
   68-character measure. */
.page {
  max-width: 68ch;
  margin: 0 auto;
  padding: clamp(2.5rem, 7vw, 4.5rem) clamp(1rem, 5vw, 1.5rem) 3rem;
}

/* ---------- Masthead ---------- */

.masthead {
  text-align: center;
  /* The gap below the masthead comes from .subhead's own bottom margin (which
     collapses through), so the same value sits above and below the tagline and
     it lands exactly midway between the logo and the carousel. */
  --subhead-gap: clamp(1.25rem, 3.5vw, 1.9rem);
  margin-bottom: 0;
}

/* The h1 now holds the logo image rather than text. line-height:0 removes the
   descender gap browsers reserve beneath an inline image. */
.masthead__logo {
  margin: 0;
  line-height: 0;
}

/* Both lockups are wide now — the finalist is 3.84:1, the A/B variant 4.02:1 —
   so one rule covers them: run well across the column, stay short. */
.masthead__logo img {
  display: inline-block;
  width: clamp(230px, 55%, 340px);
  height: auto;
}

.subhead {
  margin: var(--subhead-gap) 0;
  font-size: clamp(0.9rem, 3vw, 1.05rem);
  font-weight: 400;
  color: var(--ink-soft);
  letter-spacing: 0.02em;
}

/* ---------- Carousel ---------- */

.carousel { margin-bottom: clamp(2rem, 5vw, 3rem); }

/* The stage is the window onto the ring.

   Overflow stays visible on purpose. The slides either side of the centre are
   meant to spill past the text column, and what ends them is the opacity
   falloff in script.js rather than a hard edge. On a narrow screen the body's
   own overflow-x:hidden does the clipping. */
.carousel__stage {
  position: relative;
  height: var(--frame-h);
  margin: 0;
  padding: 0;
  list-style: none;
  /* Dragging up and down still scrolls the page; sideways is ours. */
  touch-action: pan-y;
  cursor: grab;
}

.carousel__stage.is-dragging { cursor: grabbing; }
.carousel__stage:focus-visible { outline: 2px solid var(--accent); outline-offset: 6px; }

/* Every slide fills the stage and centres its own picture inside itself. That
   way the point each picture is scaled about is the middle of the stage,
   whether it is the wide photo or the narrow video — which is what keeps the
   middle of the ring still while it turns.

   No transition here: script.js drives the movement frame by frame instead.
   See the note above animateTo() for why. */
.carousel__slide {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  /* Four permanent compositing layers, so that moving and fading them frame by
     frame never costs a layout or a repaint. */
  will-change: transform, opacity;
  /* With JS off nothing sets these, so the first slide is left showing alone
     rather than all four stacked on top of each other. */
  opacity: 0;
}

.carousel__slide:first-child { opacity: 1; }

.carousel__slide img,
.carousel__slide video {
  display: block;
  height: 100%;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  background: #fff;
  /* Just enough shadow to read as a card standing in space rather than a
     picture pasted flat on the page. */
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.15);
}

/* Only the slide at the front is properly interactive — that is what keeps the
   video's own controls usable. Its two neighbours take a single click, to
   bring themselves round to the front. Anything further round the ring is
   invisible and takes nothing.

   The <li> stays pointer-events:none throughout: it is as wide as the whole
   stage, so letting it take clicks would put a neighbour's hit area straight
   over the slide in front. The click arrives by bubbling up from the picture
   instead, which is exactly as wide as it looks. */
.carousel__slide[data-pos="active"] > *,
.carousel__slide[data-pos="near"] > * { pointer-events: auto; }

.carousel__slide[data-pos="near"] > * { cursor: pointer; }

/* Out of sight but still read aloud, which is the whole point of it — so not
   display:none, since a live region that is not rendered is never announced.
   Same technique as .honeypot further down. */
.carousel__status {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  margin: 0;
}

.carousel__controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin-top: 1rem;
}

/* Never disabled — the ring joins up, so there is no first or last slide. */
.carousel__arrow {
  border: 1px solid var(--rule);
  background: #fff;
  color: var(--ink);
  font-family: var(--font);
  font-size: 1.2rem;
  line-height: 1;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  cursor: pointer;
  transition: border-color 150ms, background 150ms;
}

.carousel__arrow:hover { border-color: var(--ink); }

.carousel__dots { display: flex; gap: 0.5rem; }

.carousel__dot {
  width: 7px;
  height: 7px;
  padding: 0;
  border: 1px solid var(--ink-soft);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: background 150ms;
}

.carousel__dot[aria-selected="true"] { background: var(--ink); border-color: var(--ink); }

/* ---------- Body copy ---------- */

.copy p { margin: 0 0 1.4rem; }

.copy h2 {
  margin: 2.2rem 0 0.9rem;
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.equipment {
  border: 1px solid var(--rule);
  padding: 0.65rem 1rem;
  margin: 0 0 1.4rem;
}

.equipment summary {
  cursor: pointer;
  font-weight: 500;
  list-style-position: inside;
}

.equipment summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.equipment ul {
  margin: 0.8rem 0 0.3rem;
  padding-left: 1.2rem;
}

.equipment li { margin-bottom: 0.35rem; }

/* ---------- Enquire ---------- */

.enquire-bar { text-align: center; margin-top: 2.2rem; }

.btn {
  font-family: var(--font);
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: #fff;
  background: var(--accent);
  border: 1px solid var(--accent);
  padding: 0.75rem 2.4rem;
  cursor: pointer;
  transition: opacity 150ms;
}

.btn:hover { opacity: 0.82; }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.enquire-thanks {
  margin: 1.1rem 0 0;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

/* ---------- Dialog / contact form ---------- */

.dialog {
  border: 1px solid var(--ink);
  padding: 0;
  width: min(30rem, calc(100vw - 2rem));
  max-height: calc(100dvh - 2rem);
  color: var(--ink);
  background: #fff;
  font-family: var(--font);
}

.dialog::backdrop { background: rgba(0, 0, 0, 0.45); }

.dialog__form {
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}

.dialog__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}

.dialog__head h2 {
  margin: 0;
  font-size: 1.3rem;
  font-weight: 600;
}

.dialog__close {
  border: none;
  background: none;
  color: var(--ink-soft);
  font-family: var(--font);
  font-size: 1.6rem;
  line-height: 1;
  padding: 0 0.2rem;
  cursor: pointer;
}

.dialog__close:hover { color: var(--ink); }

.field { display: flex; flex-direction: column; gap: 0.35rem; }

.field label, .field legend {
  font-size: 0.82rem;
  letter-spacing: 0.03em;
  color: var(--ink-soft);
  padding: 0;
}

.field input[type="text"],
.field input[type="email"],
.field input[type="date"],
.field textarea {
  font-family: var(--font);
  font-size: 0.95rem;
  color: var(--ink);
  background: #fff;
  border: 1px solid var(--rule);
  padding: 0.55rem 0.65rem;
  width: 100%;
}

.field input:focus, .field textarea:focus {
  outline: none;
  border-color: var(--ink);
}

.field textarea { resize: vertical; }

.field--dates { border: none; margin: 0; padding: 0; min-width: 0; }

.dates { display: flex; gap: 0.75rem; }
.dates__one { flex: 1 1 0; display: flex; flex-direction: column; gap: 0.35rem; min-width: 0; }

.field--check {
  flex-direction: row;
  align-items: flex-start;
  gap: 0.6rem;
}

.field--check input { margin-top: 0.35rem; flex: 0 0 auto; }
.field--check label { font-size: 0.88rem; color: var(--ink); line-height: 1.5; }

.btn--submit { margin-top: 0.3rem; }

.btn:disabled { opacity: 0.55; cursor: default; }

/* Spam trap — hidden from people, still filled in by bots. Not display:none,
   because some bots skip fields they can tell are hidden that way. */
.honeypot {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  margin: 0;
}

.form-error {
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.5;
  color: #a3231d;
}

.form-error a { color: inherit; }

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

.site-footer {
  border-top: 1px solid var(--rule);
  padding: 2rem 1rem 2.5rem;
  text-align: center;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.site-footer p { margin: 0 0 0.35rem; }
.site-footer a { color: var(--ink); }

/* ---------- Narrow screens ---------- */

@media (max-width: 30rem) {
  .dates { flex-direction: column; gap: 0.8rem; }
  .btn { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  /* The ring itself is layout rather than motion, so it stays; script.js drops
     the travel between positions and cuts straight to the new one. */
  * { scroll-behavior: auto !important; }
}
