/* OrbitLab landing page (/). Loaded only by templates/landing.html, after the
   shared theme, components and portal sheets, so it uses their tokens and adds
   nothing to any other page.

   One signature, everything else quiet: the hero is the visitor's own sky,
   and its nightfall (sky.js) is the only orchestrated motion on the page. The
   rest is set like a printed page rather than a kit of cards - ruled rows, a
   specification list, the house buttons - in the portal's existing language:
   rose for action and "you are here", teal for information, mono only for
   measured values, colour (never movement) on hover. */

/* The front door has no sidebar rail: on a wide screen the catalogue is one
   click away in the top bar and the footer, and the hero needs the width.
   Below 980px the sidebar is the drawer again, untouched. */
body[data-page="home"] .portal-shell { max-width: 1280px; }
@media (min-width: 981px) {
  body[data-page="home"] .portal-main { max-width: none; }
}
@media (min-width: 1561px) {
  body[data-page="home"] .portal-sidebar { display: none; }
}
/* Between 981px and the width at which the top bar's six links fit (1365px,
   1560px in French; portal.css measured both), this page had no navigation
   at all: the rail is hidden here, portal.css hides the links below that
   width, and the hamburger only exists under 980px. Across the band the
   hamburger comes back and the sidebar is the drawer it opens, as on a
   phone; portal.js widens its drawer query to 1560px on this page so the
   closed drawer is inert. In English from 1366px the drawer is simply never
   opened. */
@media (min-width: 981px) and (max-width: 1560px) {
  body[data-page="home"] .portal-sidebar {
    position: fixed; top: 0; inset-inline-start: 0; bottom: 0; width: 270px; z-index: 50;
    max-height: none; height: 100vh; height: 100dvh; overflow-y: auto; background: var(--app-bg);
    transform: translateX(-100%); transition: transform var(--t-med) ease; padding-top: var(--s-9);
  }
  [dir="rtl"] body[data-page="home"] .portal-sidebar { transform: translateX(100%); }
  body[data-page="home"].sidebar-open .portal-sidebar,
  [dir="rtl"] body[data-page="home"].sidebar-open .portal-sidebar { transform: translateX(0); box-shadow: 0 0 50px var(--shadow); }
  body[data-page="home"].sidebar-open::after { content: ""; position: fixed; inset: 0; z-index: 45; background: rgba(0, 0, 0, 0.5); }
  body[data-page="home"].sidebar-open .navbar { z-index: 55; }
}
@media (min-width: 981px) and (max-width: 1365px) {
  body[data-page="home"] .nav-toggle { display: flex; }
}
@media (min-width: 1366px) and (max-width: 1560px) {
  html[lang="fr"] body[data-page="home"] .nav-toggle { display: flex; }
}

/* `display` beats the `hidden` attribute, so every element this page shows
   and hides from script says so explicitly. */
.landing [hidden] { display: none !important; }

/* A text link, for "see all" beside a section title: information colour and
   a quiet underline that comes up to full strength under the pointer. Calls
   to action are buttons, never this. */
.landing-link {
  display: inline-flex; align-items: center; min-height: 44px;
  font-weight: 600; color: var(--accent-2);
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px;
  text-decoration-color: color-mix(in srgb, var(--accent-2) 45%, transparent);
  transition: color var(--t-med) ease, text-decoration-color var(--t-med) ease;
}
.landing-link:hover { color: var(--text); text-decoration-color: currentColor; }

/* ---------------- hero ---------------- */
.landing-hero { padding: var(--s-7) 0 var(--s-8); }
.landing-hero-grid {
  display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: var(--s-8) var(--s-9); align-items: center;
}
.landing-hero-copy { display: flex; flex-direction: column; gap: var(--s-6); min-width: 0; }
.landing-title {
  margin: 0; font-family: var(--font-display); font-size: var(--fs-hero);
  font-weight: 500; line-height: 1.02; letter-spacing: -0.02em;
  font-variation-settings: "opsz" 144;
}
.landing-line { display: block; }
.landing-lead { margin: 0; max-width: 31rem; font-size: 19px; line-height: 1.6; color: var(--text-soft); text-wrap: pretty; }
/* Two buttons of one size: the action in rose, the second way in drawn as an
   outline beside it. A bare underlined link next to a filled button read as
   an afterthought, a different height and weight from its neighbour. */
.landing-actions { margin: var(--s-2) 0 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-4); }
.landing-actions .btn { min-height: 48px; padding-inline: var(--s-6); font-size: 16px; justify-content: center; }

/* A learner part-way down a path: one block of text and one button back in,
   side by side at every width. */
.landing-back {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-4) var(--s-6);
  /* Padding at the lower step: with 16 / 24 the Continue button no longer fit
     beside the text on a 375px phone and the bar grew a row. */
  margin-bottom: var(--s-7); padding: var(--s-4) var(--s-5);
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-md);
}
/* Reserved before first paint for a returning learner (see the inline script in
   landing.html); the row is 80px on a desk and 99px on a phone once filled. */
.landing-back.is-reserved:empty { box-sizing: border-box; min-height: 76px; }
.landing-back-label { font-weight: 700; color: var(--text); }
.landing-back-line { font-size: 15px; line-height: 1.45; }
/* Shares a row with the button down to a 375px phone; only below about 180px
   of text does the button drop under it. */
.landing-back-body { flex: 1 1 180px; min-width: 0; display: flex; flex-direction: column; gap: var(--s-3); }
.landing-back-go { flex: none; min-height: 44px; }
.landing-back-rail { display: block; height: 4px; border-radius: var(--r-pill); background: var(--rule); overflow: hidden; }
.landing-back-fill { display: block; height: 100%; border-radius: var(--r-pill); background: var(--accent); }

/* ---------------- the sky ---------------- */
.landing-sky {
  margin: 0; width: 100%; max-width: 520px; justify-self: center;
  display: flex; flex-direction: column; gap: var(--s-4);
}
/* One line that reads as a sentence: "Tonight over [Dubai] at 9:00 PM". The
   time used to sit apart at the far edge, repeating "Tonight". */
.landing-sky-head {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3) var(--s-4);
  font-size: 14px; color: var(--muted);
  /* The city picker and the time land with the ephemeris; the row is reserved
     at the picker's 44px so the dome and the copy beside it do not move when
     they do (a 0.05 shift on every desk load). */
  min-height: 44px;
}
.landing-sky-when { color: var(--text-soft); font-variant-numeric: tabular-nums; }
.landing-city .lang-select { min-height: 44px; }
/* A square box the canvas fills. The canvas is absolutely positioned, so
   redrawing it can never change the box it measures itself against. */
.landing-sky-dome { position: relative; width: 100%; aspect-ratio: 1 / 1; }
.landing-sky-dome canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* The dome is a view of the night sky in either theme and paints its own
   darkness; the compass letters around it take the page's text colour (sky.js
   reads --text-soft), so on paper it is a dark disc on the page, as on /sky,
   not a black square. */
.landing-sky-cap {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--s-4) var(--s-5); font-size: 13.5px; color: var(--muted);
}
.landing-sky-cap > span { flex: 1 1 220px; }
.landing-replay { min-height: 44px; padding: var(--s-3) var(--s-5); font-size: 14px; }
[dir="rtl"] .landing-replay-icon svg { transform: scaleX(-1); }

/* ---------------- tonight's readings ---------------- */
.landing-readings {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  gap: var(--s-0); background: var(--border);
  border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden;
}
.landing-reading { display: flex; flex-direction: column; gap: var(--s-2); padding: var(--s-5) var(--s-6); background: var(--panel); }
.landing-reading-label { font-size: 13.5px; font-weight: 700; color: var(--text-soft); }
.landing-reading-value {
  font-family: var(--font-mono); font-size: 26px; font-weight: 500; line-height: 1.25;
  color: var(--accent-2); font-variant-numeric: tabular-nums;
}
.landing-reading-sub { font-size: 14px; color: var(--muted); text-wrap: pretty; }
.landing-foot { margin: var(--s-4) 0 0; font-size: 13.5px; color: var(--muted); }

/* ---------------- sections ---------------- */
.landing-section-head {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0 var(--s-7);
}
.landing-section-lead { margin: 0 0 var(--s-6); max-width: 46rem; font-size: 17px; color: var(--text-soft); }

/* ---------------- where to start: ruled rows ---------------- */
.landing-entries { border-top: 1px solid var(--rule); margin-top: var(--s-6); }
.landing-entry {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: var(--s-6) var(--s-9); align-items: start;
  padding: var(--s-7) 0; border-bottom: 1px solid var(--rule);
}
.landing-entry-text { display: flex; flex-direction: column; gap: var(--s-4); max-width: 30rem; }
.landing-entry-text p { margin: 0; color: var(--text-soft); text-wrap: pretty; }
.landing-entry-title { margin: 0; font-family: var(--font-display); font-size: var(--fs-h2); font-weight: 500; line-height: 1.15; }
.landing-entry-go { align-self: flex-start; margin-top: var(--s-2); min-height: 44px; padding: var(--s-4) var(--s-5); }
.landing-entry-specimen { min-width: 0; }

/* The lesson specimen: the photograph beside the lesson's own reading-level
   control, shown working on the lesson's real text. */
.landing-lesson { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); gap: var(--s-6); align-items: start; }
.landing-lesson-img {
  display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--r-sm); background: #0b1020;
}
.landing-levels { display: flex; flex-direction: column; gap: var(--s-4); }
.landing-levels-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-3); }
.landing-levels-label { font-size: 13.5px; font-weight: 700; color: var(--text-soft); }
.landing-levels-options { display: inline-flex; border: 1px solid var(--border); border-radius: var(--r-sm); overflow: hidden; }
.landing-level {
  min-height: 44px; padding: 0 var(--s-4); border: 0; background: transparent; cursor: pointer;
  font-family: var(--font-mono); font-size: 13px; color: var(--text-soft);
  transition: background-color var(--t-med) ease, color var(--t-med) ease;
}
.landing-level + .landing-level { border-inline-start: 1px solid var(--border); }
.landing-level:hover { color: var(--text); }
.landing-level[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink); font-weight: 600; }
.landing-level:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; box-shadow: var(--ring); }
.landing-level-text { margin: 0; min-height: 9em; font-size: 15.5px; line-height: 1.6; color: var(--text); }

/* The next dates in the sky calendar, ruled between the dates only: the row
   already has a rule above and below it, and an outer rule on the list drew
   a second line 36px inside each of them. The first date sits level with
   the heading beside it. */
.landing-cal { list-style: none; margin: 0; padding: 0; }
.landing-cal-item {
  display: grid; grid-template-columns: 5.5em minmax(0, 1fr); gap: var(--s-5);
  padding: var(--s-5) 0;
}
.landing-cal-item:first-child { padding-top: var(--s-3); }
.landing-cal-item:last-child { padding-bottom: 0; }
.landing-cal-item + .landing-cal-item { border-top: 1px solid var(--rule); }
.landing-cal-date { font-family: var(--font-mono); font-size: 13px; color: var(--accent-2); padding-top: var(--s-1); }
.landing-cal-body { display: flex; flex-direction: column; gap: var(--s-1); min-width: 0; }
.landing-cal-body b { font-size: 15.5px; }
.landing-cal-body span { font-size: 14px; color: var(--muted); }

/* The ground track is a map, and a map is a chart: it follows the theme like
   the simulator's own does. At night the sea is the deep navy of the sky
   dome and the land a shade lighter; on paper the sea is the panel tint and
   the land the border colour, a plain atlas page. The night half of the Earth
   is shaded in both. The satellite is rose: it is the position. */
.landing-track {
  --track-sea: #0b1020; --track-land: #171f3f; --track-coast: rgba(140, 160, 220, 0.38);
  --track-grid: rgba(140, 160, 220, 0.13); --track-eq: rgba(140, 160, 220, 0.3);
  --track-night: rgba(2, 3, 12, 0.5);
  margin: 0; max-width: 560px; display: flex; flex-direction: column; gap: var(--s-3);
}
[data-theme="light"] .landing-track {
  --track-sea: var(--panel-2); --track-land: var(--border); --track-coast: color-mix(in srgb, var(--muted) 55%, transparent);
  --track-grid: rgba(60, 40, 100, 0.1); --track-eq: rgba(60, 40, 100, 0.28);
  --track-night: rgba(25, 20, 48, 0.17);
}
.landing-track svg { display: block; width: 100%; height: auto; background: var(--track-sea); border-radius: var(--r-sm); }
.landing-track-land path { fill: var(--track-land); stroke: var(--track-coast); stroke-width: 0.6; stroke-linejoin: round; }
.landing-track-grid { fill: none; stroke: var(--track-grid); stroke-width: 1; }
.landing-track-eq { fill: none; stroke: var(--track-eq); stroke-width: 1; }
.landing-track-night { fill: var(--track-night); stroke: none; }
.landing-track-all { fill: none; stroke: var(--accent-2); stroke-opacity: 0.3; stroke-width: 1.4; stroke-linejoin: round; }
.landing-track-trail { fill: none; stroke: var(--accent-2); stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; }
.landing-track-sat { fill: var(--accent); }
.landing-track figcaption { font-size: 13px; color: var(--muted); }

/* ---------------- paths and courses ---------------- */
.landing-paths {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: var(--s-0); background: var(--border);
  border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden;
}
.landing-paths > li { display: flex; background: var(--panel); }
.landing-paths-loading { padding: var(--s-5) var(--s-6); color: var(--muted); }
.landing-path {
  flex: 1; display: flex; flex-direction: column; gap: var(--s-3); padding: var(--s-5) var(--s-6);
  color: var(--text); text-decoration: none;
  transition: background-color var(--t-med) ease;
}
.landing-path:hover { background: var(--panel-2); }
.landing-path-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--s-2) var(--s-4); }
.landing-path-title { font-family: var(--font-display); font-size: 20px; font-weight: 500; }
.landing-path-meta { font-size: 13px; color: var(--muted); white-space: nowrap; }
.landing-path-sum { font-size: 15px; color: var(--text-soft); text-wrap: pretty; }

.landing-courses {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: var(--s-5); margin-top: var(--s-5);
}
.landing-course {
  display: flex; flex-direction: column; gap: var(--s-3); padding: var(--s-6) var(--s-6);
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r-md);
  color: var(--text); text-decoration: none;
  transition: border-color var(--t-med) ease;
}
.landing-course:hover { border-color: var(--accent-2); }
.landing-course--history:hover { border-color: var(--history-accent); }
.landing-course-title { font-family: var(--font-display); font-size: 21px; font-weight: 500; line-height: 1.25; }
.landing-course-meta { font-size: 13px; font-weight: 700; color: var(--muted); }
.landing-course--history .landing-course-meta { color: var(--history-accent-line); }
.landing-course-sum { font-size: 15px; color: var(--text-soft); text-wrap: pretty; }

/* ---------------- three languages, and the specifics ---------------- */
.landing-langs { list-style: none; margin: var(--s-6) 0 0; padding: 0; border-top: 1px solid var(--rule); }
.landing-langs li { display: flex; align-items: baseline; gap: var(--s-6); padding: var(--s-5) 0; border-bottom: 1px solid var(--rule); }
.landing-lang-code { flex: none; width: 2.2em; font-family: var(--font-mono); font-size: 12px; color: var(--muted); }
.landing-lang-line {
  flex: 1; min-width: 0; font-family: var(--font-display);
  font-size: clamp(24px, 3vw, 38px); line-height: 1.25;
}
/* Physical on purpose: the Arabic specimen line reads from the right in every
   language; the RTL rule below says the same thing for an Arabic page. */
.landing-lang-line[lang="ar"] { text-align: right; line-height: 1.6; letter-spacing: 0; }
[dir="rtl"] .landing-lang-line { text-align: right; }

/* Four terms, so four columns or two, never three: auto-fit put three on a
   1024px laptop and left "Cost" alone on a second row. */
.landing-spec {
  margin: var(--s-7) 0 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-6) var(--s-8);
}
.landing-spec > div { display: flex; flex-direction: column; gap: var(--s-2); }
.landing-spec dt { font-weight: 700; color: var(--text); }
.landing-spec dd { margin: 0; color: var(--text-soft); text-wrap: pretty; }

/* ---------------- Arabic ----------------
   No letter-spacing: the script is drawn joined, so extra reading room goes
   into the line height instead. */
html[lang="ar"] .landing-title { letter-spacing: 0; line-height: 1.45; }
html[lang="ar"] .landing-level-text,
html[lang="ar"] .landing-lead { line-height: 1.9; }

/* ---------------- motion ----------------
   The headline arrives in two beats - "Look up." then the rest - and the
   readings follow. Short, once, and nothing loops except the satellite
   (landing.js), which stops off screen. */
@keyframes landing-rise {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: none; }
}
@keyframes landing-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}
.landing-rise { animation: landing-rise var(--t-slow) var(--ease-out) both; }
.landing-fade { animation: landing-fade var(--t-slow) ease-out both; }
.landing-d0 { animation-delay: var(--t-fast); }
.landing-d1 { animation-delay: var(--t-med); }
.landing-d2 { animation-delay: var(--t-slow); }
.landing-d3 { animation-delay: var(--t-slow); }
/* The strip rises as one piece: its dividers are the container showing
   through 1px gaps, so fading the cells one by one flashed the whole
   container colour as a solid block while they were still transparent. */
.landing-readings { animation: landing-rise var(--t-slow) var(--ease-out) both; }
.landing-level-text.is-swapped { animation: landing-fade var(--t-med) ease-out; }

@media (prefers-reduced-motion: reduce) {
  .landing-rise,
  .landing-fade,
  .landing-readings,
  .landing-level-text.is-swapped { animation: none; }
  .landing-link,
  .landing-level,
  .landing-path,
  .landing-course { transition: none; }
}

/* ---------------- narrow screens ---------------- */
@media (max-width: 980px) {
  .landing-hero-grid { grid-template-columns: minmax(0, 1fr); }
  .landing-sky { max-width: 460px; }
  .landing-entry { grid-template-columns: minmax(0, 1fr); padding: var(--s-7) 0; }
  .landing-spec { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* A phone's first screen has to carry the thesis: the headline, the one
   action and the sky itself, above the tab bar. Measured at 375x812 before
   this block, the dome began at y=768 - entirely below the fold - because the
   button ran full width over its own row, the sky header wrapped onto two
   lines and the stack was spaced for a desk. */
@media (max-width: 560px) {
  .landing-back.is-reserved:empty { min-height: 99px; }
  /* The text's flex basis makes room for the Continue button beside it; at 180px
     the two no longer shared the row once the button took the 16px step. */
  .landing-back-body { flex-basis: 150px; }
  .landing-hero { padding: var(--s-2) 0 var(--s-7); }
  .landing-hero-grid { gap: var(--s-6); }
  .landing-hero-copy { gap: var(--s-5); }
  .landing-lead { font-size: 17px; }
  /* The two buttons split the row evenly, and each takes the full width if a
     longer language pushes the second onto its own line. */
  .landing-actions { margin-top: 0; gap: var(--s-4); }
  .landing-actions .btn { flex: 1 1 auto; padding-inline: var(--s-5); }
  .landing-spec { grid-template-columns: minmax(0, 1fr); gap: var(--s-5); }
  .landing-sky { max-width: 330px; gap: var(--s-3); }
  .landing-back { padding: var(--s-4) var(--s-5); gap: var(--s-4); margin-bottom: var(--s-6); }
  .landing-back-line { font-size: 14px; }
  .landing-readings { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .landing-reading { padding: var(--s-5); }
  .landing-reading-value { font-size: 21px; }
  .landing-lesson { grid-template-columns: minmax(0, 1fr); }
  .landing-lesson-img { aspect-ratio: 16 / 9; }
  .landing-langs li { gap: var(--s-5); }
}

/* The simulations row's specimen: a transit and its light curve. */
.landing-transit { margin: 0; min-width: 0; }
.landing-transit svg { display: block; width: 100%; background: var(--instrument-bg); border: 1px solid var(--rule); border-radius: var(--r-sm); }
.transit-star { fill: var(--history-accent-line); }
.transit-orbit { stroke: var(--muted); stroke-dasharray: 4 6; fill: none; }
.transit-planet { fill: var(--instrument-bg); stroke: var(--text-soft); }
.transit-axis { stroke: var(--border); fill: none; }
.transit-light { stroke: var(--accent-2); stroke-width: 2; fill: none; }
.transit-marker { stroke: var(--accent); stroke-dasharray: 3 4; fill: none; }
.transit-point { fill: var(--accent); }
.landing-transit figcaption { font-size: 14px; color: var(--muted); line-height: 1.6; padding-top: var(--s-4); }
.landing-sky-status { position: absolute; inset: 0; display: grid; place-content: center; margin: 0; text-align: center; padding: var(--s-7); color: var(--muted); z-index: 1; }
.landing-sky-status button { margin-top: var(--s-4); justify-self: center; }
@media (max-width: 560px) {
  .landing-hero-copy { gap: var(--s-5); }
}
