/* ==========================================================================
   Freight Sentinel — splash page
   Built from Figma "Freight Sentinel Landing Page"
     desktop  78:130   1440 × 1048
     tablet  117:12    1194 ×  834
     mobile  117:13     390 ×  844
   ========================================================================== */

:root {
  --cream:  #E5DBC7;   /* rgb(229, 219, 199) — page + footer ground        */
  --accent: #A83E22;   /* rgb(168,  62,  34) — marker bars, button, marks  */
  --error:  #D92626;   /* rgb(217,  38,  38) — validation                  */
  --ink:    #000000;   /* body copy                                        */

  --mark-ink:   var(--cream);    /* text inside the accent bars   */
  --field-ink:  var(--accent);   /* input text and placeholder    */
  --field-bg:   rgba(255, 255, 255, 0.5);   /* Figma desktop frame's fill */
  --footer-ink: var(--accent);   /* footer tagline and copyright  */

  --font: "Helvetica Neue", Helvetica, Arial, "Liberation Sans", sans-serif;

  --gutter: 40px;

  /* Vertical scale.
     Every element in the vertical stack is capped against `vh` as well as its
     design size, so the composition shrinks to fit rather than overflowing.
     The page must never scroll at any aspect — a landscape phone has barely a
     third of the height a portrait one does, and the design size simply does
     not fit there. The vh figures below sum to roughly 90vh at the tightest,
     leaving headroom for the gaps. Retune them together, not individually. */
  --pad-top:    min(32px, 4vh);
  /* One shared height for both masthead marks, so the shield and the wordmark
     always scale together instead of drifting apart under different caps. */
  --brand-h:    min(46px, 5.8vh);
  --h1:         min(48.2px, calc((100vw - 32px) / 7.988), 7.4vh);
  --lede-size:  min(20px, 2.55vh);
  --gap-1:      min(24px, 3vh);
  --gap-2:      min(28px, 3.5vh);
  --field-h:    min(38px, 4.7vh);
  --field-gap:  min(8px, 1vh);
  --panel-pad:  min(10px, 1.2vh);
  --footer-h:   min(58px, 7.2vh);
  --footer-pad: min(19px, 2.4vh);
}

/* --------------------------------------------------------------------------
   Themes — `?theme=white` / `?theme=black` on the URL, applied by the inline
   script in index.html. Both drop the photograph and everything that exists to
   fight it (the lede's cream wash, the form's panel), leaving the type on a
   flat ground.
   -------------------------------------------------------------------------- */

[data-theme="white"] {
  --cream: #FFFFFF;
  --ink: #000000;
  --mark-ink: #FFFFFF;
  /* White on white is invisible — tint the field instead. */
  --field-bg: rgba(168, 62, 34, 0.06);
}

[data-theme="black"] {
  --cream: #000000;
  --ink: #E5DBC7;
  --mark-ink: #E5DBC7;
  --field-ink: #E5DBC7;
  --field-bg: rgba(229, 219, 199, 0.09);
  /* Accent on black is only ~3:1 — too low for 12px footer type. */
  --footer-ink: #E5DBC7;
}

[data-theme] .backdrop__road,
[data-theme] .lede::before { display: none; }

[data-theme] .lede { text-shadow: none; }

/* The vertical composition is tuned to sit above the photograph's horizon.
   With no photograph that bias just opens a void between the form and the
   footer, so ease it off and let the block settle nearer the centre. */
[data-theme] .hero { padding-bottom: clamp(16px, 5vh, 44px); }

/* Nothing separates a flat footer from a flat page, so the mark and copyright
   read as floating. A hairline gives the footer an edge to sit on. */
[data-theme] .footer__bar { position: relative; }

[data-theme] .footer__bar::before {
  content: "";
  position: absolute;
  top: 0;
  left: 20px;
  right: 20px;
  height: 1px;
  background: var(--accent);
  opacity: 0.55;
}


@media (min-width: 768px) {
  [data-theme] .footer__bar::before {
    left: var(--gutter);
    right: 39px;
  }
}

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

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

body {
  margin: 0;
  font-family: var(--font);
  color: var(--ink);
  background: var(--cream);
}

img, svg { display: block; }

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

/* --------------------------------------------------------------------------
   Shell — one viewport tall, footer pinned to the bottom
   -------------------------------------------------------------------------- */

.page {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  /* Horizontal only — the headline bars hang outside the content column.
     Vertical overflow must stay scrollable so short viewports don't clip. */
  overflow-x: hidden;
}

/* --------------------------------------------------------------------------
   Backdrop
   The photography is greyscale; the sepia comes from multiplying it over the
   cream ground, exactly as the Figma layers do. `isolation` keeps the blend
   contained so the foreground copy stays untouched.
   -------------------------------------------------------------------------- */

.backdrop {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--cream);
  isolation: isolate;
  pointer-events: none;
}

.backdrop__road {
  position: absolute;
  inset: 0;
  mix-blend-mode: multiply;
  background-repeat: no-repeat;
  /* ?v= is a cache buster — bump it whenever the photo is re-exported, or
     browsers holding the previous file will keep showing it.
     Phones get the 1600px cut: at 125vw a 430px screen asks for ~1070 device
     pixels, so the 3168px master is 550KB of nothing. */
  background-image: url("assets/road-sm.jpg?v=3");
  /* `cover`, not the Figma crop percentages.
     The frames define a crop for three exact sizes and nothing in between, and
     every attempt to carry those numbers across breaks somewhere: a width-tuned
     zoom blows the photo up at in-between widths, a percentage offset slices the
     sky off short frames, and a viewport-height floor over-zooms tall ones into
     nothing but sky. `cover` cannot over-zoom — it always uses the smallest
     scale that fills the frame — so the composition survives every aspect. The
     cost is that the photo reads slightly wider than the Figma frames. */
  /* 115% of `cover` — a touch of zoom so there is vertical overflow for the
     position to act on; at exactly `cover` a tall phone shows the whole frame
     height and the vertical framing has no effect. Biased left of centre and
     low to favour the highway over the sky. */
  background-size: max(125vw, 125vh) auto;
  background-position: 18% 82%;
}

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

.masthead {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: var(--pad-top) 32px 0;
}

.masthead__mark,
.masthead__logo img {
  flex: none;
  width: auto;
  height: var(--brand-h);
}

.masthead__mark { color: var(--accent); }

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

.hero {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  /* The composition sits a little above true centre in every frame; the offset
     is expressed against viewport height so it eases off on short screens.
     106px at the 844px mobile frame. */
  padding-top: min(16px, 2vh);
  padding-bottom: clamp(16px, 12.56vh, 106px);
}

/* The 310px column the lede and form sit in. The headline bars are positioned
   against it and are allowed to hang outside, as they do in the Figma frames. */
.hero__inner {
  width: 310px;
  max-width: calc(100% - 80px);
  margin: 0 auto;
}

/* --- Headline -------------------------------------------------------------
   Each line is its own block so the accent bar hugs the text. The staggered
   indents reproduce the leading spaces baked into the Figma text layer.
   -------------------------------------------------------------------------- */

.headline {
  margin: 0;
  /* The staggered bars span 7.99em from the leftmost to the rightmost edge, so
     capping the type at (viewport − 2 × 16px gutter) / 7.99 guarantees neither
     bar can touch a screen edge. 48.2px at the 390px mobile frame and above. */
  font-size: var(--h1);
  font-weight: 400;
  line-height: 1.35;          /* 65 / 48.2 — matches 81 / 60 on desktop */
  letter-spacing: 0;
  text-transform: uppercase;
}

/* The staggered bars are wider on the left than the right, so the block's ink
   sits left of the column's centreline — 39px of it at desktop in the Figma
   frames themselves. Centre it by shifting the block to the column's midpoint
   minus half the ink box (the em constant is the ink box's own centre, derived
   from the per-breakpoint stagger offsets and bar widths). Expressed this way
   it self-corrects for any column width or type size, so the headline stays
   centred as the type scales down on narrow screens. Applied as a relative
   offset so no line can rewrap. Re-derive the constant if the stagger changes. */
.headline {
  position: relative;
  left: calc(50% - 3.164em);
}

.headline__line { display: block; }

.mark {
  display: inline;
  padding: 0.06em 0.21em;
  background: var(--accent);
  color: var(--mark-ink);
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

.headline__line--1 { margin-left:  0.249em; }
.headline__line--2 { margin-left:  1.349em; }
.headline__line--3 { margin-left: -0.830em; }

/* --- Lede ----------------------------------------------------------------- */

.lede {
  width: 100%;
  margin: var(--gap-1) auto 0;
  font-size: var(--lede-size);
  font-weight: 300;
  line-height: 1.3;           /* 26 / 20 */
  text-align: center;
  /* The design sets black copy straight onto the photo, which only reads while
     the sky is behind it. On short frames the composition compresses and the
     lede drifts onto the trucks, so it carries its own cream field: a soft
     radial wash with no hard edge, plus a tight halo on the glyphs. Against the
     sky both are invisible; against anything dark they keep the copy legible.
     This is a deliberate departure from the Figma frames. */
  position: relative;
  text-shadow:
    0 0 5px rgba(229, 219, 199, 0.98),
    0 0 12px rgba(229, 219, 199, 0.92),
    0 0 26px rgba(229, 219, 199, 0.75);
}

.lede::before {
  content: "";
  position: absolute;
  inset: -34px -52px;
  z-index: -1;
  background: radial-gradient(
    ellipse at center,
    rgba(229, 219, 199, 0.72) 0%,
    rgba(229, 219, 199, 0.58) 38%,
    rgba(229, 219, 199, 0.26) 64%,
    rgba(229, 219, 199, 0) 100%
  );
}

/* --- Signup --------------------------------------------------------------- */

.signup {
  width: 100%;
  margin: var(--gap-2) auto 0;
  padding: var(--panel-pad);
  background: var(--cream);
}

.signup__form {
  display: flex;
  flex-direction: column;
  gap: var(--field-gap);
  margin: 0;
}

.signup__input,
.signup__button {
  height: var(--field-h);
  border-radius: 0;
  font-family: inherit;
  /* Sized off the control, not fixed: --field-h shrinks with the viewport, and
     a fixed 10px label ends up filling a shrunken box. 0.263 lands on the
     Figma 10px at the design height of 38px. Letter-spacing is in em for the
     same reason — 0.1em and 0.3em are the frame's 1px and 3px at 10px. */
  font-size: clamp(8px, calc(var(--field-h) * 0.263), 10px);
  text-align: center;
}

/* The field was reading as a hollow outline next to a solid button. It gets
   the Figma desktop frame's white-50% fill back (dropped in an earlier pass),
   a heavier rule, and type a third larger than the button's — a field people
   are meant to type into should not be the quietest thing on the page. */
.signup__input {
  border: 1.5px solid var(--accent);
  background: var(--field-bg);
  color: var(--field-ink);
  font-size: clamp(9px, calc(var(--field-h) * 0.35), 14px);
  font-weight: 500;
  letter-spacing: 0.06em;
}

.signup__input::placeholder {
  color: var(--field-ink);
  opacity: 1;
}

.signup__input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.signup__button {
  border: 0;
  background: var(--accent);
  color: #FFFFFF;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 120ms ease;
}

.signup__button:hover { background: #94371E; }

.signup__button[disabled] {
  opacity: 0.65;
  cursor: default;
}

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

/* Error state */
.signup__error {
  margin: 4px 0 0;
  color: var(--error);
  font-size: 9px;
  font-weight: 400;
  line-height: 1.21;
  text-align: center;
}

.signup.is-invalid .signup__input {
  border-color: var(--error);
  color: var(--error);
}

.signup.is-invalid .signup__input::placeholder { color: var(--error); }

/* Success state */
.signup__success {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: var(--field-h);
  margin: 0;
  background: var(--accent);
  color: #FFFFFF;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-transform: uppercase;
}

.signup__check {
  flex: none;
  width: 12px;
  height: 12px;
}

[hidden] { display: none !important; }

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

.footer {
  position: relative;
  z-index: 1;
}

.footer__bar {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--footer-h);
  padding: var(--footer-pad) 39px var(--footer-pad) var(--gutter);
  background: var(--cream);
}

.footer__tagline { display: none; }

@media (min-width: 768px) {
  .footer__bar { justify-content: space-between; }
  .footer__tagline { display: block; text-transform: none; }
}

.footer__tagline,
.footer__legal {
  margin: 0;
  color: var(--footer-ink);
  font-size: 12px;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.12px;
}

.footer__legal {
  display: flex;
  align-items: center;
  gap: 10px;
  text-transform: uppercase;
}

.footer__flag {
  flex: none;
  width: 29px;
  height: 20px;
}

/* ==========================================================================
   Tablet — Figma 117:12 (1194 × 834)
   ========================================================================== */

@media (min-width: 768px) {

  /* The type sits at the Figma pixel sizes and does not grow with the frame.
     The vh terms are fit caps only — they let it shrink so the page never
     scrolls, but nothing exceeds the design size. */
  :root {
    --pad-top: min(42px, 5vh);
    --brand-h: min(68px, 8.2vh);
    --h1:      min(48.2px, 7.4vh);
  }

  /* Full-resolution master from 768px up, where the zoom asks for it. */
  .backdrop__road { background-image: url("assets/road.jpg?v=3"); }


  /* Gentle zoom over `cover` — see the desktop note. Keeps the horizon from
     sinking on short tablet frames without over-zooming tall ones. */
  .backdrop__road {
    background-size: max(145vw, 145vh) auto;
    background-position: 14% 79%;
  }

  .masthead { padding: var(--pad-top) 42px 0; }

  /* 138px at the 834px tablet frame. */
  .hero { padding-bottom: clamp(0px, 16.55vh, 138px); }

  .headline {
    font-size: var(--h1);
    left: calc(50% - 3.124em);
  }

  .headline__line--1 { margin-left:  0.21em; }
  .headline__line--2 { margin-left:  1.31em; }
  .headline__line--3 { margin-left: -0.87em; }

}

/* ==========================================================================
   Desktop — Figma 78:130 (1440 × 1048)
   ========================================================================== */

@media (min-width: 1200px) {

  :root {
    --h1:        min(60px, 7.4vh);
    --lede-size: min(24px, 2.9vh);
  }

  /* The source is square, so `max(Kvw, Kvh)` is exactly K% of `cover` — it can
     never under-fill. 130% pulls the framing back toward the Figma desktop
     frame without reintroducing the over-zoom this file kept falling into. */
  .backdrop__road {
    background-size: max(145vw, 145vh) auto;
    background-position: 14% 79%;
  }

  .masthead { padding: 42px 39px 0; }

  /* 110px at the 1048px desktop frame. */
  .hero {
    padding-bottom: clamp(16px, 10.5vh, 110px);
  }

  /* The Figma desktop frame puts this column at x=531 of 1440 — about 25px
     right of centre. Centred here instead; the offset read as a mistake. */
  /* The Figma content column starts at x=531 of 1440 (36.875%), 428 wide. */
  .hero__inner {
    width: 428px;
    margin-left: 36.875%;
  }

  .headline {
    font-size: var(--h1);
    left: calc(50% - 2.917em);
  }

  .headline__line--1 { margin-left:  0;       }
  .headline__line--2 { margin-left:  1.10em;  }
  .headline__line--3 { margin-left: -1.083em; }

  .lede {
    margin-top: var(--gap-1);
    font-size: var(--lede-size);
    line-height: 1.25;        /* 30 / 24 */
    text-align: left;
  }

  .signup { margin-top: var(--gap-2); }

  /* Input and button side by side, 200px each — the Figma desktop frame.
     Tablet and mobile stack them, as their frames do. */
  .signup__form { flex-direction: row; }

  .signup__input,
  .signup__button { flex: 1 1 200px; min-width: 0; }

  .signup__success { margin: 0 auto; }

  /* Hairline rule inset by the gutter, sitting on the footer's top edge. */
  .footer__bar { position: relative; }

  .footer__bar::before {
    content: "";
    position: absolute;
    top: 0;
    left: var(--gutter);
    right: 39px;
    height: 1px;
    background: var(--accent);
    opacity: 0.5;
  }
}

/* ==========================================================================
   Landscape phones — under 1000px wide and on their side.
   ========================================================================== */

@media (max-height: 700px) {
  /* Same reasoning as the landscape rule below, for short frames of any width
     — a 1024 x 600 window has no room for the photograph's horizon offset. */
  .hero { padding-bottom: min(24px, 4vh); }
}

@media (orientation: landscape) and (max-width: 999px) {

  /* The vh caps are sized for portrait, where height is the scarce dimension.
     On a phone turned sideways they shrink the masthead to nothing while there
     is width to spare, so lift both marks against a looser vh budget. */
  :root { --brand-h: min(58px, 11vh); }

  /* The upward bias exists to clear the photograph's horizon; on a frame this
     short it just costs height the larger marks now need. */
  .hero { padding-bottom: min(16px, 3vh); }


  /* Three quarters of the text column. With the whole composition compressed
     into ~400px of height, a full-width field and button read as a heavy bar
     across the page; narrower keeps them a compact call to action. Landscape
     tablets and desktops (1000px and wider) keep the full column. */
  .signup { width: 75%; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
