/* ================================================================ landing (signed out)
   The grid (founder's pick 2026-10-06, after essential.gg): the page sits on a 12-column grid (4 on phones) whose
   cells are divided by 1 px rules (no column lines behind the text), inside one framed column. The hero is the
   copy on the left and, on the right, the real village screenshot above one ruled invite card; then How it works as one row of four cells,
   the block wordmark at its full size with the sample world beside it, and the footer. Every colour is a theme token (diorama.css), so each theme draws it; the
   default theme is "grid". Spacing steps: 8, 16, 24, 32, 48, 64. */
:root {
  --lw-max: var(--frame-max); --lw-cols: 12; --lw-pad: 32px;
}

/* The wordmark is one big shulker box: a pale rim on top, the lid above a dark seam, the shell below,
   and a little loot inside. --wm-grass/dirt/stone keep their names for the block roles. */
:root {
  --wm-grass: #cba5dc; --wm-dirt: #a274b8; --wm-stone: #8a5ea1; --wm-seam: #3b2449; --wm-coal: #5b3a6e;
  --wm-iron: #5fd37e; --wm-gold: #f0c341; --wm-diamond: #5fe0d3; --wm-shirt: #e0674f; --wm-pants: #2f3a5a;
}
:root[data-theme="sunset"] { --wm-shirt: #3f7fc4; }
:root[data-theme="night"], :root[data-theme="grid"] { --wm-grass: #e2c6ee; --wm-dirt: #b98bcc; --wm-stone: #a57abb; --wm-seam: #2a1838; --wm-coal: #6d4a80; --wm-pants: #2a3150; }

/* First paint: theme.js sets data-view on <html> before any stylesheet loads, so the right view paints
   first; app.mjs render() keeps the final say. */
:root[data-view="landing"] .layout { display: block; max-width: none; padding: 0; }
:root[data-view="landing"] .layout > .stage, :root[data-view="landing"] .layout > .panel { display: none; }
:root[data-view="owner"] #landing { display: none; }
:root[data-view="landing"] #account-label { display: none; }
body[data-page="home"][data-view="welcome"] .topbar-right > .swatches { display: none; }
#landing[hidden] { display: none; }

/* Hero test arms (hero-arm.js sets data-hero on <html> before first paint): only the chosen arm's lines show.
   Without the attribute (script blocked) the control, arm a, shows. Arms b and d were dropped 2026-10-07 (Keiden,
   website owner); a is the only arm left, and the mechanism stays for the next test. */
:root[data-hero="a"] [data-hero-arm]:not([data-hero-arm~="a"]),
:root:not([data-hero]) [data-hero-arm]:not([data-hero-arm~="a"]) { display: none; }

/* ---------------------------------------------------------------- the frame and its rules */
:root[data-view="landing"] .topbar-row, .lw {
  max-width: var(--lw-max); margin: 0 auto; border-inline: 1px solid var(--rule-strong); position: relative;
}
:root[data-view="landing"] .topbar-row { height: 64px; padding: 0 var(--lw-pad); border-bottom: 1px solid var(--rule-strong); }
:root[data-view="landing"] .brand-mark { width: 26px; height: 26px; filter: none; }
.lw { animation: none; }
.lw-grid-row { position: relative; display: grid; grid-template-columns: repeat(var(--lw-cols), minmax(0, 1fr)); border-top: 1px solid var(--rule-strong); }
.lw-grid-row:first-child { border-top: 0; }

/* ---------------------------------------------------------------- hero */
.lw-copy { grid-column: 1 / 8; padding: 48px var(--lw-pad); min-width: 0; align-self: center; }
.lw-title { font: 800 clamp(2.6rem, 5.4vw, 4.4rem)/.95 var(--font-display); letter-spacing: -.048em; max-width: 9.5em; text-wrap: balance; }
.lw-lede { margin-top: 22px; font-size: 19px; line-height: 1.5; color: var(--ink-2); max-width: 31em; text-wrap: pretty; }
.lw .banner { margin-top: 22px; }
/* The hero's one button (Keiden, website owner, 2026-10-07: like Aternos and Apex, one big "Claim yours now"). It opens
   the door card below the picture (app.mjs); the card stays hidden until then, or until an invite arrives. */
:root[data-view="landing"] .lw-cta { margin-top: 28px; height: 60px; padding: 0 36px; font-size: var(--text-lg); font-weight: 700; }
/* "Already have a server? Sign in" is a sentence, so it is set in the body face (mono is for what a player types exactly,
   DESIGN-SYSTEM rule 5), one step under the button (Keiden, website owner, 2026-10-08). */
.lw-cta-note { margin-top: var(--space-4); font-size: var(--text-sm); }
#landing:not([data-door="invite"]):not([data-door="account"]):not([data-door="waitlist"]) .lw-card { display: none; }
.lw-side { grid-column: 8 / 13; display: flex; flex-direction: column; border-left: 1px solid var(--rule-strong); min-width: 0; }

/* The real village screenshot (#1405) in the hero's right cell, above the invite card: 16:9 from the img's own
   width and height, so it holds its box before it loads (no layout shift). */
.lw-media-hero { padding: var(--space-4) var(--lw-pad); }
.lw-media-hero picture { display: block; max-width: 500px; margin-inline: auto; }
.lw-media-hero img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; border-radius: var(--radius); }
/* Until the door card opens, on a wide screen the picture fills its whole cell (inset by the column padding), as tall as
   the copy and the three steps beside it, so the cell holds no empty rules above and below a floating 16:9 strip
   (Keiden, website owner, 2026-10-08). The players stand just right of centre; the crop keeps them and the well.
   The box is the cell's, so nothing shifts while the picture loads. */
@media (min-width: 901px) {
  #landing:not([data-door="invite"]):not([data-door="account"]):not([data-door="waitlist"]) .lw-media-hero { position: relative; flex: 1; min-height: 320px; padding: 0; }
  #landing:not([data-door="invite"]):not([data-door="account"]):not([data-door="waitlist"]) .lw-media-hero picture { position: absolute; inset: var(--lw-pad); max-width: none; margin: 0; }
  #landing:not([data-door="invite"]):not([data-door="account"]):not([data-door="waitlist"]) .lw-media-hero img { height: 100%; aspect-ratio: auto; object-position: 56% 50%; }
}
/* The invite card: the one primary action, ruled off from the picture above it. */
.lw-card { padding: 24px var(--lw-pad) 28px; border-top: 1px solid var(--rule-strong); }
.lw-world { position: relative; width: 240px; height: 220px; }
.lw-halo { position: absolute; inset: 8% 6%; pointer-events: none; opacity: .9;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--sky-top, #9fd3f3) 62%, transparent) 0%,
    color-mix(in srgb, var(--sky-bottom, #eaf5fa) 45%, transparent) 58%, transparent 100%); }
.lw-world[data-night="true"] .lw-halo { opacity: 1; }
.lw-slot { position: absolute; inset: 0;
  -webkit-mask-image: radial-gradient(closest-side, #000 78%, transparent 100%); mask-image: radial-gradient(closest-side, #000 78%, transparent 100%); }
.lw-slot canvas { display: block; width: 100%; height: 100%; outline: none; }
#landing .bs-replay { width: 100%; height: 100%; }
/* The SVG fallback uses external styles under the sealed script/style CSP. */
.bs-replay-fallback svg { width: 100%; height: 100%; display: block; }
.lw-drag { position: absolute; left: 12px; top: 10px; margin: 0; transition: opacity .6s; pointer-events: none; }
.lw-world.touched .lw-drag, .lw-world[data-replay="none"] .lw-drag, .lw-world[data-replay="fallback"] .lw-drag { opacity: 0; }
.lw-cap { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 16px; padding-top: 12px; }
.lw-cap p { margin: 0; display: flex; align-items: center; gap: 0; white-space: nowrap; min-width: 0; }
.lw-cap-l #lw-day { color: var(--ink); font-weight: 600; }
.lw-dot { margin: 0 9px; color: var(--ink-3); }
.lw-cap-r { gap: 14px !important; }
.lw-cap-r button { font: inherit; letter-spacing: inherit; text-transform: inherit; color: inherit; background: none; border: 0; border-bottom: 1px solid transparent; padding: 2px 0; cursor: pointer; }
.lw-cap-r button:hover, .lw-cap-r button:focus-visible { color: var(--ink); border-color: var(--ink); }
.lw-sample { display: inline-block; border: 1px dashed var(--line-3); border-radius: 999px; padding: 3px 8px; }
/* Every small mono caps line (kicker aside) is one voice: one size, one tracking, one colour. */
.lw-cap, .lw-sample, .lw-drag, #wordmark-motion { font: 500 var(--text-xs)/1.4 var(--font-mono); letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3); }

/* The invite door: the one primary action. Squared to the grid; every landing button and input is 48 px. */
.lw-door, .lw-card > .lw-waitlist, #landing-account { max-width: 540px; }
.lw-door { margin-top: 0; }
.lw-invite .label { margin-bottom: var(--space-3); font: 600 var(--text-sm)/1.4 var(--font-body); color: var(--ink); }
.lw-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(140px, .7fr); gap: 8px; align-items: start; }
.lw-digits { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 6px; }
/* #invite-entry outranks diorama.css's input:not([type]) rule, which padded each 37 px box 16 px a side and clipped the digit. */
#invite-entry .lw-digits input, .lw-digits input { width: 100%; height: 48px; padding: 0; text-align: center; font: 600 20px/48px var(--font-mono); font-variant-numeric: tabular-nums; border-radius: 4px; }
:root[data-view="landing"] .btn { height: 48px; border-radius: 4px; }
.lw-row .btn { width: 100%; }
.lw-hint { margin-top: var(--space-3); font-size: var(--text-sm); }
.lw-msg { margin-top: var(--space-2); font-size: var(--text-sm); color: var(--danger); }
.lw-msg:empty { display: none; }
.lw-alt { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 16px; margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--rule-strong); }
.lw-alt p { margin: 0; font-size: var(--text-sm); color: var(--ink-2); }
#landing[data-door="waitlist"] .lw-alt, #landing[data-door="account"] .lw-alt { display: none; }
#landing:not([data-door="waitlist"]) #waitlist { display: none; }
#landing:not([data-door="account"]):not([data-open-signup][data-door="invite"]) #app > .welcome { display: none; }
/* Arrived with an invite (app.mjs sets data-invited while one is saved and nobody is signed in): one ready line
   stands where the code boxes and the waitlist row were, and the account card leads the side column on every width,
   ahead of the picture. A full fleet still shows its waitlist offer inside the account card (app.mjs). */
.lw-ready { display: none; }
#landing[data-invited] .lw-ready { display: block; margin: 0; font: 600 var(--text-lg)/1.3 var(--font-display); color: var(--ink); }
#landing[data-invited] .lw-invite, #landing[data-invited] .lw-alt { display: none; }
#landing[data-invited] .lw-media-hero { order: 2; border-top: 1px solid var(--rule-strong); }
#landing[data-invited] .lw-card { border-top: 0; }
/* Open sign-up (D-170; app.mjs sets data-open-signup from /v1/auth/config): "Claim yours now" opens the account card, and
   one line over it, "Open to everyone for now. Have an invite code?", keeps the code boxes one tap away. The waitlist
   offer then comes only from a full fleet (inside the account card). Invite-only keeps the code boxes and the waitlist
   button, without that line. */
#landing:not([data-open-signup]) .lw-open-line { display: none; }
#landing[data-open-signup] .lw-alt [data-door-open="waitlist"] { display: none; }
#landing[data-open-signup]:not([data-door="invite"]) .lw-invite { display: none; }
#landing[data-open-signup][data-door="invite"] .lw-alt { display: none; }
/* With open sign-up the code door keeps the account card under the boxes: a code is optional, signing up is not. */
#landing[data-open-signup][data-door="invite"] #landing-account { margin-top: var(--space-5); }
#landing[data-open-signup]:not([data-invited])[data-door="account"] .lw-alt { display: flex; margin-top: 0; padding-top: 0; border-top: 0; }
#landing #app > .loading-note, #landing .swatches { display: none; }

/* ---------------------------------------------------------------- media band and How it works */
/* How it works: the kicker and heading on one line, then the three steps as ruled cells. */
.lw-kicker { font: 500 var(--text-xs)/1.4 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--accent-ink); }
.lw-steps { list-style: none; margin: 0; padding: 0; counter-reset: step; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.lw-steps li { counter-increment: step; border-left: 1px solid var(--rule-strong); font: 600 var(--text-base)/1.35 var(--font-display); letter-spacing: -.01em; }
.lw-steps li::before { content: "0" counter(step); display: block; margin-bottom: var(--space-2); font: 500 var(--text-xs)/1 var(--font-mono); letter-spacing: .08em; color: var(--accent-ink); }

/* ---------------------------------------------------------------- footer: the wordmark and the sample world, then one dense mono row */
/* The block wordmark at its production size (min(100%, 760px), founder 22:5x PT: "keep the big shulker box text t
   bottom"), centred in its share of the row above the footer links, its pause under it on the right. wordmark.js
   draws 40 px of sky plus about 12% of the width; the slot holds that before the script arrives (no layout shift).
   The sample world sits in the row's last three columns, its rule in line with step 03's (#1405); between 901 and
   1199 px it is the phone size (200 x 180), so it fits those three columns and the shorter wordmark leaves no gap. */
.lw-word-wrap { grid-column: 1 / 10; align-self: center; justify-self: center; width: min(100% - 2 * var(--lw-pad), 760px); display: flex; flex-direction: column; padding: 16px 0; }
.lw-foot > .lw-accent { grid-column: 10 / -1; display: grid; justify-items: center; align-content: center; padding: 16px 16px 12px; border-left: 1px solid var(--rule-strong); }
@media (min-width: 901px) and (max-width: 1199px) {
  .lw-foot > .lw-accent { padding-inline: 8px; }
  .lw-foot .lw-world { width: 200px; height: 180px; }
}
.lw-word { width: 100%; min-height: calc(47px + min(12vw - 4px, 91px)); }
.wm canvas { display: block; width: 100%; touch-action: pan-y; -webkit-user-select: none; user-select: none; }
#wordmark-motion { align-self: flex-end; margin-top: 8px; border: 0; border-bottom: 1px solid transparent; background: none; padding: 4px 0; cursor: pointer; }
#wordmark-motion:hover, #wordmark-motion:focus-visible { color: var(--ink); border-color: var(--ink); }
.lw-foot > .owner-footer { grid-column: 1 / -1; align-content: start; margin: 0; padding: 20px var(--lw-pad) 24px; border-top: 1px solid var(--rule-strong) !important; display: flex; flex-wrap: wrap; justify-content: space-between; gap: 10px 24px; }
.lw-foot .small-print { font: 500 var(--text-xs)/1.5 var(--font-mono); color: var(--ink-3); margin: 0; }
.lw-foot .small-print a { color: var(--ink-2); font-weight: 500; }
.lw-foot .small-print:nth-last-child(-n+2) { font-family: var(--font-body); }
.lw-foot .small-print:nth-last-child(2) { flex-basis: 100%; padding-top: 14px; border-top: 1px solid var(--rule); }

#landing-account > .panel { padding: 0; width: 100%; }
/* The sign-in card sits one 24 px step under the invite hint (style.css zeroes #app > .card margins). */
#landing[data-door="account"] #landing-account { margin-top: var(--space-5); }
.lw-card .intro { display: none; }
.lw-card .welcome { margin-top: 24px; }
.lw-signin, .lw-other-code { border: 0; padding: 0; background: none; cursor: pointer; }
#auth-status:empty { display: none; }
/* "Sign in" (header or hero) points at the login card: a static outline for 1.2 s, with a pulse when motion is allowed. */
.signin-pulse { outline: 3px solid var(--focus); outline-offset: 4px; animation: signin-pulse 1.2s ease-out; }
@keyframes signin-pulse { from { box-shadow: 0 0 0 14px var(--focus-ring); background: var(--accent-soft); } }

/* Decorative texture must not introduce a data-image source under img-src self. */
body .stage-sky::after, body .sky::after { background-image: repeating-radial-gradient(circle at 17% 31%, var(--ink) 0 .5px, transparent .75px 1.5px); background-size: 7px 11px; opacity: .015; }

/* Sign-in card: one button system. From 400 px wide the submit and the other door (Create account / Sign in
   instead) sit side by side at equal width; narrower, each takes the full width so neither label wraps. Continue
   with Google always spans the card, its mark pinned left and its words centred. All three are 48 px with the
   shared button radius, type and 4 px edge; 12 px of space between them (the form's 16 px row gap holds the edge). */
#login { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--space-3); }
#login > :not(button), #login > button.google { grid-column: 1 / -1; }
#app #login > button { justify-self: stretch; width: 100%; height: 48px; min-height: 48px; margin-bottom: 0; padding-inline: var(--space-4); }
#app #login > .google { position: relative; padding-inline: var(--space-7); }
/* An invited card leads with Google (filled), then this quiet line, then the email form. */
#login > .login-or { margin: 0; text-align: center; font-size: var(--text-sm); color: var(--ink-3); }
#app #login > .google svg { position: absolute; left: var(--space-4); top: 50%; transform: translateY(-50%); }
/* Under 400 px the Google button keeps "Continue with Google" on one line down to a 320 px phone: the text stays
   centred and clears the mark (16 px in, 18 px wide) with less padding. */
@media (max-width: 399px) { #login { grid-template-columns: minmax(0, 1fr); } #app #login > .google { padding-inline: var(--space-6); } }
/* Create first (app.mjs): an invited arrival's server form. The help line sits under its field as on the Create form;
   Create my server spans the card at the sign-in buttons' 48 px; the note and "Sign in instead" are quiet and centred. */
#create-first .opt { font-weight: 500; color: var(--ink-3); }
#create-first > .field-help { margin-top: calc(-1 * var(--space-2)); }
#app #create-first > button:not(.text-link) { justify-self: stretch; width: 100%; height: 48px; min-height: 48px; margin-bottom: 0; }
#create-first > .create-first-note { margin: 0; text-align: center; font-size: var(--text-sm); color: var(--ink-3); }
#create-first > .text-link { justify-self: center; border: 0; padding: 0; background: none; font: inherit; font-size: var(--text-sm); cursor: pointer; }
/* An account without an invite pastes its link on its own row of the Create form. */
.create-card form .invite-field { grid-column: 1 / -1; }

/* The waitlist: a card under the hero lede, signed out only. */
.card.lw-waitlist { margin-top: 24px; padding: 24px; }
.lw-wl-fields { display: grid; gap: 14px; }
.lw-wl-intro { color: var(--ink-2); font-size: var(--text-sm); line-height: 1.5; margin-top: calc(-1 * var(--space-1)); }
.lw-waitlist .label { margin: 0; }
.lw-waitlist [hidden] { display: none; }
.lw-waitlist .label > input { margin-top: 8px; }
.lw-wl-play { border: 0; margin: 0; padding: 0; min-width: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.lw-wl-play legend { padding: 0; margin-bottom: 8px; }
.lw-wl-play label { display: inline-flex; align-items: center; gap: 8px; padding: 9px 14px; border: 1.5px solid var(--line-2); border-radius: 999px; background: var(--surface-3); font-size: var(--text-sm); cursor: pointer; }
.lw-wl-play label:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-ink); }
.lw-wl-play label:has(input:focus-visible) { box-shadow: 0 0 0 4px var(--focus-ring); }
.lw-wl-play input { accent-color: var(--accent); margin: 0; }
.lw-waitlist .btn { justify-self: start; }
.lw-wl-status:empty { display: none; }
.lw-wl-status { margin-top: var(--space-3); font-size: var(--text-sm); color: var(--ink-2); }
.lw-waitlist[data-state="done"] .lw-wl-fields { display: none; }
.lw-waitlist[data-state="done"] .lw-wl-status { margin-top: 0; font-weight: 600; color: var(--ink); }
.lw-waitlist[data-state="error"] .lw-wl-status { color: var(--danger); }
.lw-waitlist .lw-wl-privacy { margin-top: var(--space-3); font-size: var(--text-xs); }
@media (max-width: 560px) {
  .card.lw-waitlist { padding: 16px; }
  .lw-waitlist .btn, .lw-alt .btn { justify-self: stretch; width: 100%; }
}

/* A changed release (app.mjs) on a tab that should not reload by itself. */
.update-note { position: fixed; z-index: 50; left: 50%; bottom: 16px; transform: translateX(-50%); width: max-content; max-width: calc(100% - 32px); margin: 0; padding: 10px 16px; border-radius: 999px; background: var(--toast-bg); color: var(--toast-ink); font-size: var(--text-sm); box-shadow: var(--shadow); }
.update-note .text-link { color: inherit; background: none; border: 0; padding: 0; font: inherit; font-weight: 600; cursor: pointer; }


/* The three steps sit in the hero's left column under the copy (Alex 2026-10-07: "too much empty space"); the side column spans both rows. */
.lw-hero { grid-template-rows: minmax(0, 1fr) auto; }
.lw-hero .lw-copy { grid-row: 1; }
.lw-hero .lw-side { grid-row: 1 / 3; }
.lw-steps-wrap { grid-column: 1 / 8; grid-row: 2; border-top: 1px solid var(--rule-strong); }

/* Every band below the copy (Three steps, the four ideas, the questions) is one ruled row with the same rhythm: a
   --space-6 top, a --text-xl heading in the display face, --text-base text, one rule weight (--rule-strong) between
   rows and cells, and the hero's column line between the heading and the text (Keiden, website owner, 2026-10-08). */
.lw-band-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-3); padding: var(--space-6) var(--lw-pad) var(--space-4); }
.lw-h2, .lw-idea-h { font: 800 var(--text-xl)/1.15 var(--font-display); letter-spacing: -.03em; text-wrap: balance; }
.lw-steps li { padding: 0 var(--lw-pad) var(--space-5); }
.lw-steps li:first-child { border-left: 0; }
.lw-idea-h { grid-column: 1 / 8; padding: var(--space-6) var(--lw-pad); }
.lw-idea-p, .lw-faq { grid-column: 8 / -1; border-left: 1px solid var(--rule-strong); }
.lw-idea-p { padding: var(--space-6) var(--lw-pad); font-size: var(--text-base); line-height: 1.5; color: var(--ink-2); text-wrap: pretty; }
.lw-faq dt { padding: var(--space-5) var(--lw-pad) 0; font-weight: 600; color: var(--ink); }
.lw-faq dt:first-child { padding-top: var(--space-6); }
.lw-faq dt + dd { padding: var(--space-1) var(--lw-pad) var(--space-5); line-height: 1.5; color: var(--ink-2); text-wrap: pretty; }
.lw-faq dd + dt { border-top: 1px solid var(--rule-strong); }
.lw-faq a { text-decoration-thickness: 1.5px; text-underline-offset: 3px; }
/* "Questions." stays in view beside its five answers instead of leaving a tall empty cell under it. */
@media (min-width: 901px) { .lw-idea-h:has(+ .lw-faq) { position: sticky; top: 0; align-self: start; } }

/* ---------------------------------------------------------------- phones and narrow windows */
@media (max-width: 900px) {
  :root { --lw-cols: 4; --lw-pad: 16px; }
  .lw-copy, .lw-side { grid-column: 1 / -1; }
  .lw-copy { padding-top: 24px; padding-bottom: 12px; }
  .lw-title { font-size: clamp(2.35rem, 10.5vw, 3.4rem); }
  .lw-lede { font-size: var(--text-base); margin-top: var(--space-3); }
  .lw-row { grid-template-columns: minmax(0, 1fr); }
  .lw-side { border-left: 0; }
  .lw-word-wrap, .lw-foot > .lw-accent { grid-column: 1 / -1; }
  .lw-word-wrap { padding: 32px 0 0; }
  .lw-foot > .lw-accent { margin-top: 16px; padding: 16px var(--lw-pad) 20px; border-left: 0; border-top: 1px solid var(--rule-strong); }
  .lw-world { width: 200px; height: 180px; }
  .lw-band-head { padding: var(--space-5) var(--lw-pad) var(--space-4); }
  .lw-steps { grid-template-columns: minmax(0, 1fr); }
  .lw-steps li { border-left: 0; border-top: 1px solid var(--rule-strong); padding: var(--space-4) var(--lw-pad) var(--space-5); }
  .lw-hero { grid-template-rows: auto auto auto; }
  .lw-hero .lw-copy { grid-row: 1; }
  .lw-hero .lw-side { grid-row: 2; }
  .lw-steps-wrap { grid-column: 1 / -1; grid-row: 3; border-top: 1px solid var(--rule-strong); }
  .lw-idea-h, .lw-idea-p, .lw-faq { grid-column: 1 / -1; border-left: 0; }
  .lw-idea-h { padding: var(--space-5) var(--lw-pad) 0; }
  .lw-idea-p { padding: var(--space-2) var(--lw-pad) var(--space-5); }
  .lw-faq dt, .lw-faq dt:first-child { padding-top: var(--space-4); }
  .lw-faq dt + dd { padding-bottom: var(--space-4); }
  /* On a phone the invite card, once open, comes first, so Continue stays on the first screen; the picture follows it, and the
     sample world sits under the wordmark. */
  .lw-media-hero { order: 2; padding: 16px var(--lw-pad) 20px; border-top: 1px solid var(--rule-strong); }
  .lw-card { border-top: 0; padding-top: 4px; }
  .lw-foot > .owner-footer { padding: 20px var(--lw-pad) 28px; display: grid; justify-content: stretch; justify-items: start; gap: 10px; }
  :root[data-view="landing"] .lw-cta { margin-top: 20px; width: 100%; }
}
