/* roman.ma — landing page.
   One screen, no scroll. Everything that matters is in the HTML; this file
   only places and dresses it. */

:root {
  --black: #000000;
  --accent: #B3382C;      /* the app's muted crimson */
  --orange: #F06A1E;      /* the mark's orange — the wordmark takes it too, so
                             the lockup is one colour rather than two that
                             nearly match */
  --parchment: #EFE9DD;   /* warm off-white — the one primary action */
  --text: #FFFFFF;
  --text-secondary: rgba(255, 255, 255, 0.70);
  --text-muted: rgba(255, 255, 255, 0.45);

  /* Height of the black band the picture starts below, so the lockup has
     ground of its own instead of sitting on the arches. Big enough to clear
     the page's top padding plus the wordmark: 5vh + a ~2rem mark at the sizes
     those two clamp to. Keep it in step with .page's padding-top — if that
     grows, the wordmark drops into the picture again. */
  --brand-band: clamp(4.75rem, 10vh, 6.75rem);
  --brand-fade: clamp(1.25rem, 3vh, 2rem);

  --serif: "EB Garamond", Garamond, Georgia, "Times New Roman", serif;
  --sans: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;            /* the page is one screen, never scrolled */
  color: var(--text);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* The black belongs to the root, not to <body>. A background on <body> is
   painted as a normal element background — above any negatively-stacked
   child — so it would cover .bg rather than sit behind it. On <html> it goes
   to the canvas instead, underneath everything. */
html { background: var(--black); }

/* Background.
   Two files, one picture, exact transposes of each other: landing.webp is
   941x1672 and landing-large.webp is 1672x941. The rule is `cover`, so the
   image scales to fill the viewport and the overflow is cropped rather than
   squashed — the aspect ratio is never touched, which is the whole difference
   between this and a stretch.

   The switch is on the *shape of the viewport*, not on a device width. What a
   `cover` background is cropped by is the ratio, and nothing else: a portrait
   tablet at 768px wide is a portrait window and wants the portrait file, while
   a phone held sideways is a landscape window and wants the landscape one. A
   min-width breakpoint gets both of those wrong. Squares are landscape here —
   the two rules meet at 1/1 and the wide file wins it.

   The crop is anchored at 25% down on the portrait file, not centred. Centring
   a 9:16 image in a taller-than-wide window still lands low, on the dark
   floor, and throws the arches off the top; 25% holds the three arches in
   frame and keeps the floor under the button, where the text needs the dark.
   The landscape file is already the shape of the window it is going into, so
   it is centred and barely cropped at all.

   WebP only: the PNG this used to fall back to has never existed in the repo,
   and a fallback that 404s is worse than none. Every browser that has shipped
   since 2020 reads WebP. */
.bg {
  position: fixed;
  inset: var(--brand-band) 0 0 0;
  background-color: var(--black);
  background-repeat: no-repeat;
  background-size: cover;
  background-position: 50% 25%;
  background-image: url("../assets/landing.webp");
  z-index: 0;

  /* The offset alone would draw a hard rule across the top of the page, which
     reads as a rendering fault rather than as a matte. The mask fades the
     first --brand-fade of the picture out to nothing so the band and the
     arches meet in a gradient.

     It masks the grain and the scrim with it — they are children of this
     element — which is what should happen: all three fade in together, so the
     top of the image is never briefly unscrimmed. Prefixed copy first for
     Safari before 15.4; the unprefixed one wins wherever it is understood. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 var(--brand-fade));
  mask-image: linear-gradient(to bottom, transparent 0, #000 var(--brand-fade));
}

/* Wider than tall: desktops, and phones turned sideways. Keep this selector
   in step with the two `media` attributes on the preload links in index.html —
   the preload is what makes the background arrive with the stylesheet instead
   of after it, and preloading the file the CSS then does not use costs a
   round trip and downloads the wrong 200 KB. */
@media (min-aspect-ratio: 1/1) {
  .bg {
    background-image: url("../assets/landing-large.webp");
    background-position: 50% 50%;
  }
}

/* Grain. Neither file is as wide as the screen it can land on — 1672px across
   a 2560px monitor is still an enlargement, and the softness of that is what
   reads as cheap. A little noise over the top gives the eye a sharp texture to
   hold and the upscale stops being the thing you notice. Costs no request —
   it is an SVG in the stylesheet. */
.bg::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
  background-size: 160px 160px;
  opacity: 0.055;
  mix-blend-mode: overlay;
  pointer-events: none;
}

/* Scrim: a vertical wash so the wordmark and the button always have ground
   under them, plus a soft pool low in the frame, under the headline and the
   row of features, so neither is read against a lit floor. */
.bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 90% 40% at 50% 82%,
      rgba(0, 0, 0, 0.55) 0%,
      rgba(0, 0, 0, 0.10) 70%,
      rgba(0, 0, 0, 0) 100%),
    linear-gradient(to bottom,
      rgba(0, 0, 0, 0.70) 0%,
      rgba(0, 0, 0, 0.20) 30%,
      rgba(0, 0, 0, 0.45) 62%,
      rgba(0, 0, 0, 0.85) 100%);
}

/* Two bands: brand at the top edge, everything else at the bottom one. The
   1fr row is empty on purpose — it is the picture's, and it is what holds the
   arches clear of type. */
.page {
  position: relative;
  z-index: 1;                  /* .bg is fixed, so it is positioned too — the
                                  content has to say it comes after it. */
  display: grid;
  grid-template-rows: auto 1fr;
  height: 100svh;
  min-height: 100%;
  padding: clamp(1.5rem, 5vh, 3rem) clamp(1.25rem, 6vw, 2.5rem);
  padding-bottom: calc(clamp(1.5rem, 5vh, 3rem) + env(safe-area-inset-bottom, 0px));
  text-align: center;
}

/* Brand.
   Mark and word on one line, centred at the top edge. The whole lockup is one
   colour, taken once on .wordmark: the word inherits it and the inline SVG
   picks it up through fill="currentColor". */
.brand { display: flex; justify-content: center; }

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;                 /* em, so the gap scales with the type */
  margin: 0;
  font-family: var(--sans);
  font-size: clamp(1.05rem, 2.6vw, 1.35rem);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--orange);
  text-shadow: 0 1px 14px rgba(0, 0, 0, 0.8);
}

/* Sized in em off the wordmark, so the two never drift apart. The bookmark is
   taller than the type it stands next to — 1.5em puts its middle on the word's
   middle and its ends just past the cap and the baseline, which is what makes
   it read as a mark rather than as an oversized letter.

   drop-shadow, not text-shadow: text-shadow does not touch an SVG fill, and
   the orange sits over a photograph that is bright in places. */
.mark {
  flex: none;
  height: 1.5em;
  width: auto;
  filter: drop-shadow(0 1px 10px rgba(0, 0, 0, 0.85));
}

/* Headline.
   Sized in the bottom band with the rest of the action, so its own max-width
   is what keeps the line breaking where it should rather than the width of a
   band it no longer has. */
.headline {
  max-width: 34rem;
  margin: 0 0 clamp(1rem, 3.5vh, 2rem);
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.9rem, 7vw, 3.25rem);
  line-height: 1.15;
  letter-spacing: -0.01em;
  text-shadow: 0 2px 24px rgba(0, 0, 0, 0.75);
}

/* Action.
   Its row is the 1fr one, so the column has to say it sits at the foot of it
   — otherwise the headline would float in the middle of the stretched box
   again, which is the thing this layout is not. */
.action {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  gap: 0.85rem;
}

/* Highlights.
   One line over the button: mark, word, dot, mark, word, dot, mark, word. They
   replace the paragraph that used to carry the pitch — at this size a sentence
   is read, and a reader deciding whether to tap does not read.

   It is a single line and must stay one, so everything here is sized off the
   label's own font-size in em and the font-size is the only thing that scales
   with the viewport. Shrink the type and the marks, the gaps and the dots all
   come with it in proportion, which is what keeps three words and two
   separators inside a 360px phone without a wrap and without a second
   breakpoint. `nowrap` is the backstop. */
.highlights {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: nowrap;
  max-width: 100%;
  margin: 0 0 clamp(0.15rem, 1vh, 0.55rem);
  padding: 0;
  list-style: none;
  font-size: clamp(0.62rem, 2.5vw, 0.8rem);
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-secondary);
  text-shadow: 0 1px 14px rgba(0, 0, 0, 0.85);
}

.highlights li {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

/* The separator is a pseudo-element rather than markup: it is punctuation
   between items, not an item. Its margins are what space the row, so the mark
   beside it uses a margin too — a `gap` on the li would land on the dot's
   inner side only and push the row off centre by that much.

   The second `content` gives it an empty alt so a screen reader reads three
   words and not "vidéos middle dot quiz". It is declared after the plain one
   rather than instead of it: a browser without the alt syntax drops the whole
   declaration, and losing the dots is worse than hearing them. */
.highlights li + li::before {
  content: "·";
  content: "·" / "";
  margin: 0 0.9em;
  color: var(--text-muted);
}

/* Stroke, not fill: the wordmark is the one solid shape on the page and these
   should not compete with it. `vector-effect` keeps the hairline at 1.5px
   however the box is sized, and the drop-shadow does for the stroke what the
   text-shadow does for the label — the row crosses a lit floor on the
   landscape crop. */
.highlights svg {
  width: 1.35em;
  height: 1.35em;
  margin-right: 0.42em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  filter: drop-shadow(0 1px 8px rgba(0, 0, 0, 0.85));
  opacity: 0.9;
}

.cta {
  display: inline-block;
  min-width: min(20rem, 100%);
  padding: 1rem 2.25rem;
  border-radius: 12px;
  background: var(--orange);
  color: #111111;            /* near-black, not white: white on this orange is
                                about 3:1, which is under the contrast a label
                                this size needs. Dark text on it is near 7:1. */
  font-size: clamp(0.95rem, 2.5vw, 1.05rem);
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  transition: transform 140ms ease, background-color 140ms ease;
}
.cta:hover { background: #FF7C33; }
.cta:active { transform: scale(0.985); }
.cta:focus-visible { outline: 2px solid var(--parchment); outline-offset: 3px; }

.note {
  margin: 0;
  font-size: 0.8rem;
  color: var(--text-muted);
}

/* Landscape phones: little vertical room, so give the type less of it. */
@media (max-height: 480px) {
  /* A band sized off the tall case would be a fifth of a sideways phone. The
     lockup is smaller here too, so it needs less of one. */
  :root { --brand-band: 3.1rem; --brand-fade: 0.9rem; }

  .headline {
    font-size: clamp(1.4rem, 5vh, 2rem);
    margin-bottom: 0.6rem;
  }
  .cta { padding: 0.75rem 1.75rem; }
  .note { display: none; }

  /* The row is one line everywhere, so sideways there is nothing to reflow —
     only the space around it to give back. */
  .action { gap: 0.6rem; }
  .highlights { margin-bottom: 0; font-size: 0.68rem; }
}

@media (prefers-reduced-motion: reduce) {
  .cta { transition: none; }
}
