/* ---------------------------------------------------------------------------
   Floza
   The logo arrived first and set the terms: deep navy ground, one gradient that
   runs cyan to purple to pink. So the site is drenched navy rather than a white
   page with a navy header, and the gradient is treated as an ink that appears
   three times, not as decoration sprayed everywhere.

   Type: Poppins for anything that speaks, because the wordmark is geometric and
   rounded and the headings should sound like the same voice. Work Sans for
   reading, which is humanist and a different axis, so the two never blur into
   each other. JetBrains Mono only for the commands, where it is not costume:
   the product genuinely has a command line and those strings are literal.
--------------------------------------------------------------------------- */

@font-face { font-family: 'Poppins'; src: url('fonts/poppins-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Poppins'; src: url('fonts/poppins-700.woff2') format('woff2'); font-weight: 700; font-display: swap; }
@font-face { font-family: 'Work Sans'; src: url('fonts/work-sans-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }
@font-face { font-family: 'Work Sans'; src: url('fonts/work-sans-700.woff2') format('woff2'); font-weight: 700; font-display: swap; }
@font-face { font-family: 'JetBrains Mono'; src: url('fonts/jetbrains-mono-400.woff2') format('woff2'); font-weight: 400; font-display: swap; }

/* Dark is the default because the logo is built for it and because most of the
   people this is for work in dim rooms at the end of a day. Light exists
   because some of them do not, and because a page that cannot be printed or
   read on a bright train is a page with a hole in it.

   The light side is not the dark side inverted. Its ground is a cool near-white
   carrying a little of the brand's own blue rather than the warm cream that
   every generated page seems to reach for, and its greys are darkened until
   they pass against it: muted grey on tinted white is the most common way body
   copy ends up unreadable. */
:root {
  color-scheme: dark;
  --ink:        oklch(0.16 0.06 268);
  --ink-deep:   oklch(0.11 0.05 268);
  --ink-lift:   oklch(0.22 0.06 268);
  --edge:       oklch(0.32 0.05 268);
  --paper:      oklch(0.97 0.008 268);
  --quiet:      oklch(0.78 0.03 268);
  --cyan:       oklch(0.72 0.16 232);
  --violet:     oklch(0.56 0.24 292);
  --magenta:    oklch(0.64 0.28 348);
  --flow: linear-gradient(112deg, var(--cyan) 0%, var(--violet) 52%, var(--magenta) 100%);

  --shell: min(1180px, 92vw);
  --display: 'Poppins', system-ui, sans-serif;
  --body: 'Work Sans', system-ui, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, monospace;

  /* Named curves, shared. The built-in easings are too weak to read as
     deliberate. These live here rather than in deck.css because deck.css is
     the home page only, and a var() with no value silently drops the whole
     declaration: every transition on the Learn page was being thrown away
     with no warning and no visible error. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);

  --z-sticky: 30;
  --z-gate: 60;
}

/* Written once and pointed at twice: by the switch, and by the operating
   system when nobody has touched the switch. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;
    --glow: 0.35;
    --shadow: 0.22;
    --ink-deep:   oklch(0.985 0.004 268);
    --ink-lift:   oklch(0.955 0.006 268);
    --edge:       oklch(0.86 0.012 268);
    --paper:      oklch(0.18 0.045 268);
    --quiet:      oklch(0.44 0.035 268);
  }
}
:root[data-theme="light"] {
  color-scheme: light;
  /* The same wash is far too loud over white. */
  --glow: 0.35;
  --shadow: 0.22;
  --ink-deep:   oklch(0.985 0.004 268);
  --ink-lift:   oklch(0.955 0.006 268);
  --edge:       oklch(0.86 0.012 268);
  --paper:      oklch(0.18 0.045 268);
  --quiet:      oklch(0.44 0.035 268);
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--ink-deep);
  color: var(--paper);
  font: 400 clamp(1rem, 0.96rem + 0.2vw, 1.075rem)/1.65 var(--body);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, .display { font-family: var(--display); font-weight: 700; letter-spacing: -0.03em; line-height: 1.05; text-wrap: balance; }
p { text-wrap: pretty; }
a { color: inherit; }

.shell { width: var(--shell); margin-inline: auto; }

/* ---- the mark ---------------------------------------------------------- */
/* ---- the wordmark -------------------------------------------------------
   Set in Poppins rather than traced as paths. Tracing a logo from a picture of
   it produces letterforms that are nearly right, and nearly right is worse than
   plainly different: it reads as a bad copy of itself.

   TO USE THE REAL LOGO: drop wordmark.svg into brand/ and swap the two spans
   below for <img class="wordmark" src="brand/wordmark.svg" alt="Floza">. The
   sizes here already match. */
/* Height drives it and the width follows the picture's own proportions. The
   width and height attributes on the tag are the real pixel size, so the
   browser keeps the space before the file arrives and nothing jumps. */
/* Both are in the page and CSS decides which is seen, because an img cannot
   change its own source from a stylesheet. They are 73 and 125 KB, which is
   cheaper than the flash of the wrong one while a script swaps it. */
.wordmark { display: block; height: 30px; width: auto; }
.wordmark--dark { display: none; }
:root[data-theme="light"] .wordmark--light { display: none; }
:root[data-theme="light"] .wordmark--dark { display: block; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .wordmark--light { display: none; }
  :root:not([data-theme="dark"]) .wordmark--dark { display: block; }
}

/* The bar is the opposite ground, so the mark on it is the opposite mark.
   Written after the rules above so it wins on specificity alone. */
.top .wordmark--light { display: none; }
.top .wordmark--dark { display: block; }
:root[data-theme="light"] .top .wordmark--light { display: block; }
:root[data-theme="light"] .top .wordmark--dark { display: none; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .top .wordmark--light { display: block; }
  :root:not([data-theme="dark"]) .top .wordmark--dark { display: none; }
}
.wordmark--big { height: clamp(56px, 9vw, 100px); margin-bottom: 4px; }
.wordmark--big.wordmark--dark { display: none; }
:root[data-theme="light"] .wordmark--big.wordmark--light { display: none; }
:root[data-theme="light"] .wordmark--big.wordmark--dark { display: block; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .wordmark--big.wordmark--light { display: none; }
  :root:not([data-theme="dark"]) .wordmark--big.wordmark--dark { display: block; }
}
.wordmark--small { height: 22px; }

/* ---- top bar ----------------------------------------------------------- */
/* The opposite of whatever the page is, which falls out of the palette for
   free: paper and ink-deep swap places between the two themes, so naming them
   the other way round here inverts the bar without a second set of colours to
   keep in step. A dark page gets a light bar and a light page a dark one.

   Solid rather than translucent, because a bar that is the opposite colour has
   to stay the opposite colour when the page scrolls under it. */
.top {
  position: sticky; top: 0; z-index: var(--z-sticky);
  background: var(--paper);
  color: var(--ink-deep);
  border-bottom: 1px solid color-mix(in oklab, var(--paper) 82%, var(--ink-deep));
}
.top-in { display: flex; align-items: center; gap: 20px; padding: 14px 0; }
.top nav { margin-left: auto; display: flex; align-items: center; gap: 26px; font-size: 0.94rem; }
/* Mixed toward the bar's own ink rather than reusing the page's quiet, which
   is tuned for the opposite ground and would sit almost invisible here. */
.top nav a { color: color-mix(in oklab, var(--ink-deep) 74%, var(--paper)); text-decoration: none; }
.top nav a:hover { color: var(--ink-deep); }
/* The bar is already the opposite ground, so a button on it inverts once more
   or it disappears into the bar it sits on. */
.top .btn--go { background: var(--ink-deep); color: var(--paper); }
.top .btn--go:hover { background: color-mix(in oklab, var(--ink-deep) 88%, var(--paper)); }
.top .btn--edge { border-color: color-mix(in oklab, var(--paper) 70%, var(--ink-deep)); color: var(--ink-deep); }
@media (max-width: 720px) { .top nav a.opt { display: none; } }

/* ---- buttons ----------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  padding: 14px 28px; border-radius: 999px; border: 1px solid transparent;
  font: 700 0.98rem/1 var(--display); letter-spacing: -0.01em;
  text-decoration: none; cursor: pointer;
  transition: transform 180ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 180ms;
}
@media (hover: hover) and (pointer: fine) {
  @media (hover: hover) and (pointer: fine) {
  .btn:hover { transform: translateY(-2px); }
}
}
/* Paper on ink, ink on paper, and it swaps with the theme without a second
   rule because those two names swap with it. The gradient is the logo's and
   nothing else's: spread across every button it stops reading as the brand and
   starts reading as decoration. */
.btn--go { background: var(--paper); color: var(--ink-deep); }
.btn--go:hover { background: color-mix(in oklab, var(--paper) 88%, var(--ink-deep)); }
.btn--edge { border-color: var(--edge); color: var(--paper); background: transparent; }
.btn--edge:hover { border-color: var(--quiet); }
.btn--small { padding: 10px 20px; font-size: 0.9rem; }

.theme-btn {
  display: grid; place-items: center; width: 36px; height: 36px; padding: 0;
  border: 1px solid color-mix(in oklab, var(--paper) 74%, var(--ink-deep));
  border-radius: 999px; background: transparent;
  color: color-mix(in oklab, var(--ink-deep) 74%, var(--paper)); cursor: pointer;
  transition: color 160ms, border-color 160ms;
}
.theme-btn:hover { color: var(--ink-deep); border-color: var(--ink-deep); }
.theme-btn svg { grid-area: 1 / 1; }
/* Dark showing means the button offers light, so it wears a sun. */
.theme-moon { display: none; }
:root[data-theme="light"] .theme-sun { display: none; }
:root[data-theme="light"] .theme-moon { display: block; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .theme-sun { display: none; }
  :root:not([data-theme="dark"]) .theme-moon { display: block; }
}
.btn:focus-visible, a:focus-visible, button:focus-visible, input:focus-visible {
  outline: 2px solid var(--paper); outline-offset: 3px;
}
.top a:focus-visible, .top button:focus-visible { outline-color: var(--ink-deep); }
@media (prefers-reduced-motion: reduce) { .btn { transition: none; } .btn:hover { transform: none; } }

/* ---- hero -------------------------------------------------------------- */
.hero { padding: clamp(56px, 9vw, 116px) 0 clamp(40px, 6vw, 72px); position: relative; overflow: hidden; }
.hero::before {
  content: ''; position: absolute; inset: -40% -10% auto -10%; height: 120%;
  background: radial-gradient(60% 50% at 22% 8%, color-mix(in oklab, var(--violet) 22%, transparent), transparent 70%),
              radial-gradient(46% 40% at 88% 4%, color-mix(in oklab, var(--cyan) 16%, transparent), transparent 70%);
  opacity: var(--glow, 1);
  pointer-events: none;
}
.hero > * { position: relative; }
.hero h1 { font-size: clamp(2.4rem, 1.5rem + 4.2vw, 4.3rem); margin: 26px 0 0; max-width: 17ch; }
.hero .sub { font-size: clamp(1.06rem, 1rem + 0.5vw, 1.32rem); color: var(--quiet); max-width: 54ch; margin: 22px 0 0; }
.hero .cta { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 34px; }
.hero .under { margin-top: 16px; font-size: 0.88rem; color: var(--quiet); opacity: 0.92; }

/* ---- the commands, which are the product ------------------------------- */
.said {
  margin-top: clamp(38px, 5vw, 60px);
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
}
.said code {
  font: 400 0.9rem/1.5 var(--mono);
  background: color-mix(in oklab, var(--ink-lift) 76%, transparent);
  border: 1px solid color-mix(in oklab, var(--edge) 52%, transparent);
  border-radius: 9px; padding: 12px 14px; color: var(--paper);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.said code b { color: var(--cyan); font-weight: 400; }

/* ---- the photograph ---------------------------------------------------- */
.shot { padding: clamp(20px, 4vw, 44px) 0 clamp(56px, 8vw, 96px); }
.shot figure { margin: 0; }
.shot img {
  display: block; width: 100%; height: auto; border-radius: 14px;
  border: 1px solid color-mix(in oklab, var(--edge) 60%, transparent);
  box-shadow: 0 40px 90px -40px oklch(0 0 0 / var(--shadow, 0.9));
}
.shot figcaption { margin-top: 14px; font-size: 0.9rem; color: var(--quiet); max-width: 68ch; }

/* ---- what it does ------------------------------------------------------ */
.does { padding: clamp(56px, 8vw, 104px) 0; border-top: 1px solid color-mix(in oklab, var(--edge) 34%, transparent); }
.does h2 { font-size: clamp(1.7rem, 1.2rem + 2vw, 2.7rem); max-width: 20ch; }
.does-list { margin-top: clamp(32px, 4vw, 52px); display: grid; gap: clamp(28px, 4vw, 44px); grid-template-columns: repeat(auto-fit, minmax(268px, 1fr)); }
.does-list h3 { font-size: 1.16rem; margin: 0 0 8px; }
.does-list p { margin: 0; color: var(--quiet); font-size: 0.98rem; }
/* A rule above each one instead of a number: it groups without pretending
   the three are a sequence, which they are not. */
.does-list > div { padding-top: 22px; border-top: 2px solid var(--cyan); }

/* ---- where it runs ----------------------------------------------------- */
.runs { padding: clamp(56px, 8vw, 104px) 0; border-top: 1px solid color-mix(in oklab, var(--edge) 34%, transparent); }
.runs h2 { font-size: clamp(1.7rem, 1.2rem + 2vw, 2.7rem); max-width: 22ch; }
.runs-grid { margin-top: 40px; display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.place {
  padding: 26px; border-radius: 14px;
  background: color-mix(in oklab, var(--ink-lift) 60%, transparent);
  border: 1px solid color-mix(in oklab, var(--edge) 46%, transparent);
}
.place h3 { font-size: 1.1rem; margin: 0 0 8px; }
.place p { margin: 0 0 18px; color: var(--quiet); font-size: 0.95rem; }
/* At 74% of quiet this measured 3.92:1 on the light ground, under the 4.5
     it needs. Faded text is the most common way body copy ends up unreadable
     and the easiest to talk yourself into. */
.place .note { font-size: 0.84rem; color: var(--quiet); opacity: 0.92; margin-bottom: 0; }

/* ---- the honest comparison --------------------------------------------- */
.against { padding: clamp(56px, 8vw, 104px) 0; border-top: 1px solid color-mix(in oklab, var(--edge) 34%, transparent); }
.against h2 { font-size: clamp(1.7rem, 1.2rem + 2vw, 2.7rem); max-width: 20ch; }
.tbl { margin-top: 36px; width: 100%; border-collapse: collapse; font-size: 0.97rem; }
.tbl th, .tbl td { text-align: left; padding: 15px 14px; border-bottom: 1px solid color-mix(in oklab, var(--edge) 34%, transparent); vertical-align: top; }
.tbl th { font: 700 0.86rem/1.3 var(--display); color: var(--quiet); letter-spacing: 0.01em; }
.tbl td:first-child { color: var(--quiet); width: 34%; }
.tbl .yes { color: var(--cyan); }
.wrap-x { overflow-x: auto; }

/* ---- the gate ---------------------------------------------------------- */
.gate { padding: clamp(56px, 8vw, 104px) 0 clamp(72px, 10vw, 128px); border-top: 1px solid color-mix(in oklab, var(--edge) 34%, transparent); }
.gate-box {
  max-width: 620px; padding: clamp(28px, 4vw, 42px); border-radius: 16px;
  background: color-mix(in oklab, var(--ink-lift) 64%, transparent);
  border: 1px solid color-mix(in oklab, var(--edge) 52%, transparent);
}
.gate h2 { font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.1rem); margin: 0 0 12px; }
.gate p { color: var(--quiet); margin: 0 0 22px; font-size: 0.98rem; }
.gate-form { display: flex; gap: 10px; flex-wrap: wrap; }
.gate input {
  flex: 1 1 220px; min-width: 0; padding: 14px 16px; border-radius: 10px;
  border: 1px solid var(--edge); background: var(--ink-deep); color: var(--paper);
  font: 400 1rem var(--body);
}
.gate input::placeholder { color: color-mix(in oklab, var(--quiet) 82%, transparent); }
.gate-say { margin: 16px 0 0; font-size: 0.92rem; min-height: 1.4em; }
.gate-say.no { color: var(--magenta); }
.gate-say.yes { color: var(--cyan); }

/* ---- foot -------------------------------------------------------------- */
.foot { padding: 40px 0 60px; border-top: 1px solid color-mix(in oklab, var(--edge) 34%, transparent); color: var(--quiet); font-size: 0.9rem; }
.foot-in { display: flex; flex-wrap: wrap; gap: 18px; align-items: center; }
.foot nav { margin-left: auto; display: flex; gap: 22px; }
.foot a { text-decoration: none; }
.foot a:hover { color: var(--paper); }

/* ---- entrance ---------------------------------------------------------- */
/* Visible by default, then lifted. A reveal that gates visibility ships a
   blank page anywhere the transition never runs. */
.lift { animation: lift 700ms cubic-bezier(0.16, 1, 0.3, 1) both; }
.lift-2 { animation-delay: 90ms; }
.lift-3 { animation-delay: 170ms; }
.lift-4 { animation-delay: 250ms; }
@keyframes lift { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .lift { animation: fadein 1ms both; }
  @keyframes fadein { to { opacity: 1; } }
}

/* ---------------------------------------------------------------------------
   The pages beyond home
   Home is a landing page and earns its own layout. These are reference pages:
   somebody arrives with a question and wants the answer, so they are quieter,
   narrower, and built from the same few pieces rather than each having a shape
   of its own.
--------------------------------------------------------------------------- */

.sr-only {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

.page-top { padding: clamp(48px, 7vw, 88px) 0 clamp(16px, 2vw, 28px); }
.page-top h1 { font-size: clamp(2rem, 1.4rem + 2.6vw, 3.2rem); max-width: 18ch; }
.page-blurb { margin: 18px 0 0; color: var(--quiet); font-size: clamp(1.02rem, 1rem + 0.35vw, 1.2rem); max-width: 52ch; }

.band { padding: clamp(32px, 5vw, 64px) 0 clamp(48px, 7vw, 88px); }
.band-h { font-size: clamp(1.3rem, 1.1rem + 1vw, 1.8rem); margin: clamp(40px, 6vw, 72px) 0 22px; }

/* A note that fills the space a thing will occupy later, and says so. */
.empty-note {
  padding: clamp(24px, 3.5vw, 36px); border-radius: 14px;
  background: color-mix(in oklab, var(--ink-lift) 62%, transparent);
  border: 1px solid color-mix(in oklab, var(--edge) 48%, transparent);
  max-width: 66ch;
}
.empty-note p { margin: 0 0 14px; color: var(--quiet); }
.empty-note p:last-child { margin-bottom: 0; }
.empty-note strong { color: var(--paper); }

.topic-list { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(248px, 1fr)); }
.topic {
  padding: 20px; border-radius: 12px;
  border: 1px solid color-mix(in oklab, var(--edge) 46%, transparent);
}
.topic h3 { font-size: 1.02rem; margin: 0 0 6px; }
.topic p { margin: 0 0 14px; color: var(--quiet); font-size: 0.92rem; }
.soon {
  font: 700 0.68rem/1 var(--display); letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--quiet); border: 1px solid color-mix(in oklab, var(--edge) 70%, transparent);
  border-radius: 999px; padding: 5px 9px; display: inline-block;
}

.price-grid { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.price {
  padding: clamp(24px, 3vw, 34px); border-radius: 14px;
  background: color-mix(in oklab, var(--ink-lift) 58%, transparent);
  border: 1px solid color-mix(in oklab, var(--edge) 48%, transparent);
}
.price h3 { font-size: 1.05rem; margin: 0; color: var(--quiet); }
.price-amount { font: 700 clamp(2rem, 1.6rem + 1.6vw, 2.8rem)/1 var(--display); letter-spacing: -0.03em; margin: 8px 0 16px; }
.price p { color: var(--quiet); }
.price > p:first-of-type + p { color: var(--paper); }

.ticks { list-style: none; padding: 0; margin: 18px 0; display: flex; flex-direction: column; gap: 9px; }
.ticks li { position: relative; padding-left: 26px; color: var(--quiet); font-size: 0.95rem; }
.ticks li::before {
  content: ''; position: absolute; left: 4px; top: 0.55em;
  width: 9px; height: 5px; border-left: 2px solid var(--cyan); border-bottom: 2px solid var(--cyan);
  transform: rotate(-45deg);
}

.qa { display: grid; gap: clamp(24px, 3vw, 36px); grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.qa h3 { font-size: 1.02rem; margin: 0 0 8px; }
.qa p { margin: 0 0 8px; color: var(--quiet); font-size: 0.96rem; }
.qa .note { font-size: 0.86rem; opacity: 0.92; }

/* Legal pages: one column, generous measure, nothing decorative. */
.prose { max-width: 68ch; }
.prose h2 { font-size: 1.12rem; margin: clamp(28px, 3vw, 40px) 0 10px; }
.prose h2:first-child { margin-top: 0; }
.prose p { margin: 0 0 14px; color: var(--quiet); }
.prose a { color: var(--paper); text-underline-offset: 3px; }
.prose .note { font-size: 0.86rem; margin-top: 28px; }

/* The footer carries nine links now, so it wraps rather than crowding. */
.foot-nav { display: flex; flex-wrap: wrap; gap: 10px 22px; margin-top: 18px; }
.foot-nav a { text-decoration: none; }
.foot-nav a:hover { color: var(--paper); }
.foot-in { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }

/* ---------------------------------------------------------------------------
   Press feedback.
   A button that does not move when pressed leaves a half-second where nothing
   has happened yet and the person is not sure the click landed. Ninety seven
   per cent is enough to feel and small enough not to read as a bounce.
--------------------------------------------------------------------------- */
.btn { transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1), background 160ms, border-color 160ms; }
.btn:active { transform: scale(0.97); }
.theme-btn:active { transform: scale(0.94); }
@media (prefers-reduced-motion: reduce) {
  .btn, .theme-btn { transition: background 160ms, border-color 160ms; }
  .btn:active, .theme-btn:active { transform: none; }
}
/* Hover only where there is a pointer, or a tap leaves the state stuck on. */
@media (hover: none) {
  .btn:hover { transform: none; }
}

/* ---------------------------------------------------------------------------
   The field behind everything.
   Fixed, behind, and untouchable. Its own stacking context so nothing on the
   page has to know it is there.
--------------------------------------------------------------------------- */
.aurora {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  display: block;
  z-index: 0;
}

/* Everything else sits above it.

   z-index alone, and position only where there is none to start with. A
   blanket `position: relative` on every child of body is the tempting version
   and it is wrong: the bar and the deck are already fixed, and overriding that
   drops the deck out of the viewport and puts the controls under the nav.

   The sticky bar and the deck controls already carry their own z-index and are
   left alone; lifting them here would only lower them. */
.deck { z-index: 1; }
body > main, body > .foot { position: relative; z-index: 1; }

/* ---------------------------------------------------------------------------
   The name field.

   One control, not three. It was a button, then a bare box, then another
   button, and the box in the middle read as something that had wandered in
   from a form. A course start card is a name and a way to begin, so that is
   what it is: a single pill with the field inside it and Begin sitting in the
   end of it, the way a search box holds its own button.

   Try it is not here any more. It is in the bar, filled, top right, on every
   page including this one, and again on the last slide as Start building.
   Three of them on one screen was not three chances to click, it was noise.
--------------------------------------------------------------------------- */
.hello {
  /* Its own class only. Wearing s-cta as well put deck.css's display:flex on
     top of this one, later sheet winning, and the pill ran the width of the
     slide. It only ever wanted that rule for the margin, so it has its own. */
  margin-top: 34px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 5px 5px 8px;
  border: 1px solid var(--edge);
  border-radius: 999px;
  transition: border-color 200ms cubic-bezier(0.23, 1, 0.32, 1);
}
/* The whole pill lights up, because the whole pill is the control. */
.hello:hover { border-color: var(--quiet); }
.hello:focus-within { border-color: var(--paper); }

.hello-in {
  flex: 0 1 180px;
  min-width: 0;
  padding: 12px 14px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--paper);
  font: 400 0.98rem/1 var(--body);
}
.hello-in::placeholder { color: var(--quiet); }
/* No ring on the field: the pill around it is already showing focus, and two
   outlines on one control is one too many. Keyboard users still see the
   border go to full paper. */
.hello-in:focus, .hello-in:focus-visible { outline: none; }

.hello-go { padding: 12px 24px; }

/* ---------------------------------------------------------------------------
   A lesson on the Learn page.

   The video is the widest thing on the page and the caption sits under it like
   a plate under a picture, because the picture is the lesson and the words are
   the label. Sixteen by nine is declared on the element rather than left to the
   file, so the poster reserves its space and the page does not jump when the
   video loads.
--------------------------------------------------------------------------- */
.lesson { margin: 0 0 44px; }
.lesson-v {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  background: var(--ink-deep);
  border-radius: 14px;
  border: 1px solid color-mix(in oklab, var(--edge) 60%, transparent);
  box-shadow: 0 30px 70px -34px oklch(0 0 0 / var(--shadow, 0.9));
}
.lesson-cap {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 14px;
  margin-top: 16px;
}
.lesson-cap strong { font: 700 1.15rem/1.3 var(--display); letter-spacing: -0.02em; }
.lesson-n {
  font: 700 0.72rem/1 var(--display);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--cyan);
}
.lesson-t { margin-left: auto; font: 400 0.85rem/1 var(--mono); color: var(--quiet); }
.lesson-say { margin: 8px 0 0; color: var(--quiet); max-width: 60ch; font-size: 0.95rem; }

/* A topic with something behind it reads differently from one that is a
   promise. Same chip, brand colour instead of grey. */
.soon--here {
  color: var(--cyan);
  border-color: color-mix(in oklab, var(--cyan) 45%, transparent);
}

/* ---------------------------------------------------------------------------
   The Learn page.

   One set of markup, two layouts. List is the default because it reads on a
   phone without becoming a column of postage stamps, and because a five item
   course wants to be read in order. Grid is there for when the library is
   twenty lessons and scanning beats reading.

   The difference between them is one class on the <ol>. Writing them as two
   separate blocks of markup would have been quicker and would have drifted
   apart the first time a title changed.
--------------------------------------------------------------------------- */

/* ---- the head: title, count, switch ------------------------------------- */

.learn-head { padding: clamp(48px, 7vw, 84px) 0 clamp(22px, 3vw, 34px); }
.learn-head-in {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px 32px;
}
.learn-head h1 { margin: 0 0 10px; }
.learn-head .page-blurb { margin: 0; }

.view-pick { display: flex; align-items: center; gap: 16px; }
.view-count { font: 400 0.85rem/1 var(--mono); color: var(--quiet); }

/* Two buttons in one pill rather than two separate ones, because they are one
   choice with two positions and separate buttons read as two actions. */
.segmented {
  display: inline-flex;
  padding: 3px;
  gap: 2px;
  border: 1px solid var(--edge);
  border-radius: 999px;
}
.seg {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 15px;
  border: 0; border-radius: 999px;
  background: transparent;
  color: var(--quiet);
  font: 700 0.85rem/1 var(--display);
  cursor: pointer;
  transition: color 160ms var(--ease-out), background 160ms var(--ease-out),
              transform 140ms var(--ease-out);
}
.seg svg { opacity: 0.85; }
@media (hover: hover) and (pointer: fine) { .seg:hover { color: var(--paper); } }
/* Instant acknowledgement that the press was heard. */
.seg:active { transform: scale(0.96); }
.seg[aria-pressed="true"] {
  background: var(--paper);
  color: var(--ink-deep);
}

/* The band under the head does not need its own top padding as well. */
.band--tight { padding-top: 0; }

/* ---- a lesson ------------------------------------------------------------ */

.lessons {
  list-style: none;
  margin: 0 0 44px;
  padding: 0;
  /* Its own measure, narrower than the shell. Stretched the full 1180 the
     blurbs ran out at about half way and left a column of nothing down the
     right of every row, which reads as a layout that failed rather than as
     space. The grid below overrides this: cards want the whole width. */
  max-width: 960px;
}

.lsn {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 340px) 1fr;
  /* The gap was the complaint and it was fair: at 18px the words started where
     the picture stopped and the two read as one crowded block. A picture needs
     air around it before text will sit beside it as a separate thing. */
  gap: clamp(26px, 4vw, 56px);
  align-items: center;
  /* Spacing between rows, never above the first one.

     Padding on every row pushed the first thumbnail down by thirty pixels in
     list and not at all in grid, so switching views made the whole page jump.
     Both layouts now start their first picture at the same line, and the
     switch changes the arrangement without moving the top of it. */
  padding: 0 0 clamp(20px, 2.6vw, 30px);
}
/* Hairlines between, not around. A rule above the first row and below the last
   boxes the list in and makes it look like a table. */
.lsn + .lsn {
  padding-top: clamp(20px, 2.6vw, 30px);
  border-top: 1px solid color-mix(in oklab, var(--edge) 38%, transparent);
}
.lsn:last-child { padding-bottom: 0; }

.lsn-shot {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 12px;
  overflow: hidden;
  background: var(--ink-lift);
  /* The screenshot is mostly light interface, so it arrives as a bright slab on
     a dark page. The inset hairline gives it an edge to stop against instead of
     bleeding into the background. */
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--paper) 14%, transparent),
              0 14px 30px -18px oklch(0 0 0 / var(--shadow, 0.9));
}
.lsn-shot img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  transition: transform 420ms var(--ease-out);
}

.lsn-num {
  position: absolute; top: 9px; left: 10px;
  min-width: 22px; height: 22px;
  display: grid; place-items: center;
  padding: 0 6px;
  border-radius: 6px;
  background: color-mix(in oklab, var(--ink-deep) 78%, transparent);
  color: var(--paper);
  font: 700 0.76rem/1 var(--display);
  backdrop-filter: blur(4px);
}
.lsn-time {
  position: absolute; right: 9px; bottom: 9px;
  padding: 3px 7px;
  border-radius: 6px;
  background: color-mix(in oklab, var(--ink-deep) 82%, transparent);
  color: var(--paper);
  font: 400 0.74rem/1 var(--mono);
  backdrop-filter: blur(4px);
}


.lsn-text h2 {
  font-size: clamp(1.2rem, 1.05rem + 0.7vw, 1.55rem);
  letter-spacing: -0.02em;
  margin: 0 0 9px;
  text-wrap: balance;
}
.lsn-link { color: inherit; text-decoration: none; }
/* One link covering the row. The picture is not a second link to the same
   place, because a reader hearing the same destination twice per row is being
   read a stutter. */
.lsn-link::after { content: ''; position: absolute; inset: 0; border-radius: 14px; }
.lsn-link:focus-visible::after { outline: 2px solid var(--paper); outline-offset: 4px; }
.lsn-link:focus-visible { outline: none; }
.lsn-text p { margin: 0; color: var(--quiet); font-size: 0.97rem; max-width: 52ch; }

@media (hover: hover) and (pointer: fine) {
  .lsn:hover .lsn-shot img { transform: scale(1.035); }
  .lsn:hover .lsn-text h2 { color: var(--cyan); }
}
.lsn-text h2 { transition: color 160ms var(--ease-out); }

/* ---- the same lessons as a grid ------------------------------------------ */

.lessons--grid {
  max-width: none;
  display: grid;
  /* Three across on a wide screen, and it finds two and one on the way down
     without a single breakpoint. */
  grid-template-columns: repeat(auto-fit, minmax(272px, 1fr));
  gap: clamp(22px, 2.6vw, 34px);
}
.lessons--grid .lsn {
  grid-template-columns: 1fr;
  gap: 14px;
  align-items: start;
  padding: 0;
  border-top: 0;
}
.lessons--grid .lsn + .lsn { border-top: 0; }
.lessons--grid .lsn-text h2 { font-size: 1.08rem; margin-bottom: 6px; }
.lessons--grid .lsn-text p {
  font-size: 0.9rem;
  /* Two lines each, so the cards line up on a shelf instead of stepping down
     the page by however long each blurb happens to be. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

@media (max-width: 620px) {
  .lsn { grid-template-columns: 1fr; gap: 14px; }
  .lsn-shot { max-width: 420px; }
  .learn-head-in { align-items: flex-start; }
}

@media (prefers-reduced-motion: reduce) {
  .lsn-shot img, .seg, .lsn-text h2 { transition-duration: 1ms; }
  .lsn:hover .lsn-shot img { transform: none; }
}

.learn-foot { color: var(--quiet); font-size: 0.95rem; max-width: 64ch; line-height: 1.7; }

/* ---- a lesson's own page ------------------------------------------------- */

.back-up {
  display: inline-flex; align-items: center; gap: 6px;
  margin-bottom: 14px;
  font-size: 0.9rem; color: var(--quiet); text-decoration: none;
}
.back-up:hover { color: var(--paper); }
.page-kicker {
  margin: 0 0 8px;
  font: 400 0.85rem/1 var(--mono);
  color: var(--cyan);
}

.lesson-v {
  display: block;
  width: 100%; height: auto;
  aspect-ratio: 16 / 9;
  background: var(--ink-deep);
  border-radius: 14px;
  border: 1px solid color-mix(in oklab, var(--edge) 60%, transparent);
  box-shadow: 0 30px 70px -34px oklch(0 0 0 / var(--shadow, 0.9));
}

.lesson-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 250px);
  gap: clamp(24px, 4vw, 56px);
  margin-top: 34px;
}
.lesson-main h2 { font-size: 1.15rem; margin: 26px 0 10px; }
.lesson-main h2:first-child { margin-top: 0; }
.lesson-main p { color: var(--quiet); max-width: 62ch; }
.lesson-main code {
  font: 400 0.92em/1.4 var(--mono);
  background: color-mix(in oklab, var(--ink-lift) 74%, transparent);
  border-radius: 5px; padding: 2px 6px; color: var(--paper);
}

.cmd-list { margin: 0; display: grid; gap: 14px; }
.cmd-list dt { margin: 0 0 3px; font-size: 0.98rem; }
.cmd-list dd { margin: 0; color: var(--quiet); font-size: 0.92rem; }

.lesson-side h2 { font-size: 0.95rem; margin: 0 0 8px; }
.side-note { color: var(--quiet); font-size: 0.9rem; margin: 0 0 12px; }
.side-link { font-size: 0.9rem; text-decoration: none; color: var(--cyan); white-space: nowrap; }
.side-link:hover { text-decoration: underline; }

@media (max-width: 760px) {
  .lesson-body { grid-template-columns: 1fr; }
}
