/* ============================================================
   Brand system — warm editorial lane.
   Ember black / Bone / Sand / Ember clay (rare) / Slate green.
   Montserrat throughout — display and body — matched to the logo's SAUNA
   line. Mobile-first.
   ============================================================ */

/* One family, every role. Montserrat is the geometric sans closest to the
   letterforms of the logo's SAUNA line, so headlines, UI and body copy all
   sit in the same register as the mark. 200/300 carry the large display
   sizes, 400–600 the text and labels. */
@import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@200;300;400;500;600;700&display=swap");

/* Perandory — the commercial display face the brand system originally
   specified. Currently NOT wired to anything (see --font-display below); the
   @font-face is kept so dropping the files into assets/fonts/ and pointing
   --font-display back at it is a one-line change. */
@font-face {
  font-family: "Perandory";
  src: url("../fonts/Perandory.woff2") format("woff2"),
       url("../fonts/Perandory.woff") format("woff");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

:root {
  --ember-black: #201b17;
  --bone: #ede6da;
  --sand: #d3c4af;
  --ember: #be5a38;
  --slate: #4a6360;
  --gold: #d7ac67;      /* warm amber gold — the sauna-glow display accent */

  --font-display: "Montserrat", -apple-system, BlinkMacSystemFont, sans-serif;
  --font-body: "Montserrat", -apple-system, BlinkMacSystemFont, sans-serif;

  --max-w: 1120px;
  --pad: clamp(1.25rem, 4vw, 2.5rem);
  --radius: 2px;
}

/* --- Reset --- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
img { max-width: 100%; display: block; }
button { font: inherit; background: none; border: none; cursor: pointer; color: inherit; }
a { color: inherit; }

/* Available to assistive tech and search, invisible on screen. Interior
   pages open straight onto content, so their <h1> lives here rather than in
   an intro band — a page with no h1 at all would be a real regression. */
/* Off-screen until focused, then a real button in the top-left corner. The
   header is five controls deep before the content begins, and on the
   membership page that is five presses in front of the thing you came for. */
.skip-link {
  position: absolute;
  left: 0.75rem;
  top: -100px;
  z-index: 100;
  padding: 0.7rem 1.1rem;
  border-radius: var(--radius);
  background: var(--bone);
  color: var(--ember-black);
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
  transition: top 0.18s ease;
}
.skip-link:focus {
  top: 0.75rem;
  /* The browser default is a blue that belongs to no part of this palette,
     and this button is bone on a photograph. */
  outline: 2px solid var(--ember-black);
  outline-offset: 2px;
}
/* main takes focus when the link lands, so the next Tab continues from the
   content — but it must never draw a ring when clicked with a mouse. */
main:focus { outline: none; }

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

html { scroll-behavior: smooth; }
/* The header is sticky, so an anchor target scrolled flush to the top lands
   underneath it. Every jumpable section clears it by its own height. */
main [id] { scroll-margin-top: 5rem; }
body {
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.65;
  color: var(--ember-black);
  background: var(--bone);
  -webkit-font-smoothing: antialiased;
}

/* Montserrat carries much more weight than the serif it replaced, so display
   type steps down: 400 for headings, 300 for the largest sizes, with tighter
   tracking as they grow. Keeps headlines in the light register of the logo's
   SAUNA line instead of turning into slabs. */
h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.14;
  letter-spacing: -0.015em;
}
h1 { font-weight: 300; letter-spacing: -0.022em; }
h1 { font-size: clamp(2.6rem, 7vw, 4.6rem); }
h2 { font-size: clamp(1.9rem, 4.5vw, 2.9rem); }
h3 { font-size: clamp(1.25rem, 2.6vw, 1.55rem); }
p  { max-width: 62ch; }

.container { max-width: var(--max-w); margin: 0 auto; padding-left: var(--pad); padding-right: var(--pad); }

/* Interior pages carry their <h1> in .sr-only and open straight onto a
   section, so a full section's top padding under the sticky header reads as
   an empty screen. The home page is exempt: its first section is the hero,
   which sets its own padding. */
body:not([data-page="home"]) main > section:first-of-type {
  padding-top: clamp(2.25rem, 5vw, 3.75rem);
}
.section { padding: clamp(3.5rem, 9vw, 7rem) 0; }
.section-tight { padding: clamp(2rem, 5vw, 3.5rem) 0; }

/* Kicker — small editorial label above headings */
/* Micro-labels echo the logo's SAUNA line: uppercase, light, widely tracked.
   The logo sets ~0.4em; UI text stops short of that so words still read as
   words — widest on standalone labels, tighter inside buttons. */
.kicker {
  display: block;
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--slate);
  margin-bottom: 1rem;
}
.dark .kicker { color: var(--sand); }

.lede { font-size: clamp(1.05rem, 2.2vw, 1.25rem); opacity: 0.85; }

/* --- Two registers --- */
.dark {
  background: var(--ember-black);
  color: var(--bone);
}
.dark a { color: var(--bone); }

/* --- Buttons: ember is rare — one primary action per screen --- */
.btn {
  display: inline-block;
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.02em;
  padding: 0.9rem 1.9rem;
  border: 1px solid transparent;   /* keeps filled & bordered buttons the same height */
  border-radius: var(--radius);
  text-decoration: none;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
  text-align: center;
}
.btn-sm { padding: 0.55rem 1.15rem; font-size: 0.85rem; }
.btn-primary { background: var(--ember); color: var(--bone); }
.btn-primary:hover { background: #a84c2d; }
/* Log in & book — calm slate green, the members' action */
.btn-book { background: var(--slate); color: var(--bone); }
.btn-book:hover { background: #3b504d; }
/* Become a member — deep ember-black on light grounds; inverts to bone
   on dark grounds (home hero header, dark CTA band) so it stays legible */
.btn-join { background: var(--ember-black); color: var(--bone); border: 1px solid var(--ember-black); }
.btn-join:hover { background: #352d26; border-color: #352d26; }
.dark .btn-join,
.hero .btn-join,
#site-header .btn-join {
  background: var(--bone); color: var(--ember-black); border-color: var(--bone);
}
.dark .btn-join:hover,
.hero .btn-join:hover,
#site-header .btn-join:hover {
  background: #fff; border-color: #fff;
}
.btn-outline { border: 1px solid var(--ember-black); color: var(--ember-black); }
.btn-outline:hover { background: var(--ember-black); color: var(--bone); }
.btn-outline-light { border: 1px solid rgba(237, 230, 218, 0.5); color: var(--bone); }
.btn-outline-light:hover { border-color: var(--bone); }
.btn-quiet { text-decoration: underline; text-underline-offset: 4px; padding: 0.9rem 0.5rem; font-weight: 500; }

/* ============ Header ============ */
/* Dark bar across the whole site. Swap --header-bg for a different register
   (e.g. a navy 27, 40, 66) — everything in the bar reads currentColor off
   --header-fg, so the one pair of variables is the whole recolour. */
:root {
  --header-bg: 32, 27, 23;      /* ember black */
  --header-fg: var(--bone);
  /* The bar's measured height — full-height sections subtract it so they end
     at the fold and not a header's worth below it. It is set by the join
     button, the tallest thing in the bar, not by the logo: 41px + the
     0.85rem padding pair + the hairline, and 46px once the button grows at
     900px. Measure again if the bar's padding or that button ever changes. */
  --header-h: 4.35rem;
}
@media (min-width: 900px) { :root { --header-h: 4.65rem; } }
#site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(var(--header-bg), 0.92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(237, 230, 218, 0.13);
  color: var(--header-fg);
}
.header-inner {
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 0.85rem var(--pad);
  display: flex;
  align-items: center;
  gap: 1.5rem;
}
.wordmark {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.45rem;
  letter-spacing: 0.14em;
  text-decoration: none;
  line-height: 1;
}

/* ---- Logo -------------------------------------------------------------
   The logo ships as a single white-on-transparent PNG used as a CSS *mask*,
   painted with currentColor. That keeps every existing colour rule working
   untouched: the mark turns bone over the dark hero header, ember black on
   the solid header, gold in the hero — same cascade the text wordmark used.
   Browsers without mask support fall back to the typeset wordmark. */
:root { --logo-aspect: 676 / 271; }

@supports (mask-image: url("../images/logo.png")) or (-webkit-mask-image: url("../images/logo.png")) {
  .wordmark {
    display: block;
    background-color: currentColor;
    aspect-ratio: var(--logo-aspect);
    width: auto;
    -webkit-mask: url("../images/logo.png") no-repeat center / contain;
    mask: url("../images/logo.png") no-repeat center / contain;
  }
  /* the brand name stays in the DOM for screen readers, search and copy-paste */
  .wordmark .wordmark-name {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0; border: 0;
    overflow: hidden; white-space: nowrap;
    clip-path: inset(50%);
  }
  /* the lockup stacks OAS over SAUNA, so it needs more height than the
     single-line type it replaces or the sub-line turns to mush */
  .wordmark { height: 2.15rem; }
  .footer-brand .wordmark { height: 2.6rem; }
}

/* Sentence-case, light and airy — set in the body face, not the tiny
   uppercase tracking the bar used to carry. */
.site-nav { display: none; gap: 2.1rem; align-items: center; }
.site-nav a {
  text-decoration: none;
  white-space: nowrap;           /* "Groups & companies" must never wrap */
  font-size: 0.88rem;
  font-weight: 400;
  letter-spacing: 0.01em;
  text-transform: none;
  opacity: 0.82;
  transition: opacity 0.15s ease;
}
.site-nav a:hover { opacity: 1; }
.site-nav a.is-active { opacity: 1; border-bottom: 1px solid currentColor; padding-bottom: 3px; }
.header-actions { display: flex; align-items: center; gap: 1.1rem; margin-left: auto; }

/* Member entrance — quiet text link + person glyph, no button weight */
.member-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  text-decoration: none;
  font-size: 0.95rem;
  font-weight: 400;
  opacity: 0.82;
  white-space: nowrap;
  transition: opacity 0.15s ease;
}
.member-link:hover { opacity: 1; }
.member-glyph { flex-shrink: 0; }

/* Header CTA — one light block, small uppercase, as in the reference */
.header-actions .btn-join,
.nav-extra .btn-join {
  text-transform: uppercase;
  letter-spacing: 0.17em;
  font-size: 0.68rem;
  font-weight: 600;
  padding: 0.8rem 1.4rem;
  border-radius: 3px;
  white-space: nowrap;
}
.header-actions { gap: 1.3rem; }

/* Drawer-only cluster: the language toggle + "become a member" live inside
   the mobile menu so the top bar stays to Boka pass + burger on small screens */
.nav-extra { display: none; }
body.nav-open .nav-extra {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 1.2rem;
  width: 100%;
  margin-top: 0.4rem;
  padding-top: 1.4rem;
  border-top: 1px solid rgba(237, 230, 218, 0.16);
}
.nav-extra .lang-toggle { font-size: 0.95rem; }

/* Below the desktop breakpoint the language toggle moves into the drawer.
   The CTA does not: the one action the site is asking for must not live
   behind a burger on the device most people arrive on. It rides in the top
   bar at button-small, and the drawer drops its copy so an open menu never
   shows the same button twice. */
@media (max-width: 899px) {
  .header-actions > .lang-toggle { display: none; }
  body.nav-open .header-actions > .btn-join { display: none; }
  /* the member link is already in the top bar here — don't repeat it */
  .nav-extra .member-link { display: none; }
  .header-actions { gap: 0.9rem; }
  .header-actions .btn-join { letter-spacing: 0.12em; padding: 0.7rem 0.95rem; font-size: 0.64rem; }
  /* the glyph carries the meaning; the word costs a whole nav bar's width */
  .header-actions .member-link span { display: none; }
}

/* The narrow phones — 320px, an SE or a folded screen. The bar is a wordmark,
   a CTA and a burger, and at this width they added up to 13px more than the
   screen: enough to make every page scroll sideways. English costs the most
   ("SECURE YOUR SPOT" against "SÄKRA DIN PLATS"), so the room has to be found
   for the longer of the two. */
@media (max-width: 380px) {
  .header-inner { gap: 0.75rem; padding-left: 1rem; padding-right: 1rem; }
  .header-actions { gap: 0.6rem; }
  .header-actions .btn-join {
    letter-spacing: 0.08em;
    padding: 0.65rem 0.7rem;
    font-size: 0.6rem;
  }
  /* it keeps its 44px height; only the box around the bars narrows */
  .nav-burger { min-width: 34px; }
}

/* On the home page the bar floats transparent over the hero, where the CTA
   would sit inches above the hero's own — so it waits until the header goes
   solid, i.e. until the hero (and its button) has scrolled away. */
@media (max-width: 899px) {
  /* visibility, not opacity: an invisible button that still takes tab focus
     and reads out to a screen reader is worse than no button. This keeps its
     space in the bar, so nothing shifts when it arrives. */
  body[data-page="home"] #site-header:not(.is-solid) .header-actions > .btn-join {
    visibility: hidden;
    opacity: 0;
  }
  .header-actions > .btn-join { transition: opacity 0.3s ease; }
}


.lang-toggle { display: flex; align-items: center; gap: 0.3rem; font-size: 0.8rem; opacity: 0.8; }
.lang-toggle button { font-weight: 500; padding: 0.2rem; }
.lang-toggle button.is-active { font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }

/* Two 2px bars and a 5px gap is a 9px object; the box around it is what makes
   it pressable. 44px square is the size a thumb expects, and it is the control
   every phone visitor uses first. */
.nav-burger {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  padding: 0;
  min-width: 44px;
  min-height: 44px;
}
.nav-burger span { width: 22px; height: 2px; background: currentColor; transition: transform 0.2s ease; }
body.nav-open .nav-burger span:first-child { transform: translateY(3.5px) rotate(45deg); }
body.nav-open .nav-burger span:last-child { transform: translateY(-3.5px) rotate(-45deg); }

/* Mobile nav drawer */
body.nav-open .site-nav {
  display: flex;
  flex-direction: column;
  position: fixed;
  inset: 57px 0 auto 0;
  background: rgb(var(--header-bg));
  border-bottom: 1px solid rgba(237, 230, 218, 0.13);
  padding: 1.5rem var(--pad) 2rem;
  gap: 1.1rem;
  font-size: 1.05rem;
}

@media (min-width: 900px) {
  /* wordmark left · nav centred in the space between · actions right.
     The nav takes the middle and centres its links, so the distance from
     the wordmark and from the buttons is equal. */
  .wordmark { flex-shrink: 0; }
  .site-nav { display: flex; flex: 1; justify-content: center; }
  .header-actions { margin-left: 0; flex-shrink: 0; flex-wrap: nowrap; }
  .nav-burger { display: none; }
}

/* Between the desktop breakpoint and ~1100px the five-item nav plus the CTA
   is tight — worst case is English, where the labels are longest. Pull the
   spacing in rather than let anything wrap or collide. */
@media (min-width: 900px) and (max-width: 1149px) {
  .site-nav { gap: 1rem; }
  .site-nav a { font-size: 0.79rem; }
  .header-inner { gap: 0.9rem; }
  .header-actions { gap: 0.75rem; }
  .header-actions .btn-join { letter-spacing: 0.09em; padding: 0.7rem 0.9rem; font-size: 0.64rem; }
  /* the person glyph carries the meaning on its own here — drop the word so
     "Groups & companies" and "The experience" still fit on one row */
  .header-actions .member-link span { display: none; }
  .header-actions .member-link { gap: 0; }
}

/* Home: header floats transparent over the cinematic hero, then turns solid
   once you scroll past it (class toggled in main.js). */
body[data-page="home"] #site-header {
  position: fixed;
  left: 0;
  right: 0;
  background: transparent;
  border-bottom-color: transparent;
  backdrop-filter: none;
  transition: background 0.35s ease, border-color 0.35s ease, backdrop-filter 0.35s ease;
}
/* Solid state (scrolled, or mobile drawer open) settles into the same dark
   bar the rest of the site carries — the bar only ever changes its ground,
   never its ink, so no colour inversions are needed here any more. */
body[data-page="home"] #site-header.is-solid,
body[data-page="home"].nav-open #site-header {
  background: rgba(var(--header-bg), 0.92);
  backdrop-filter: blur(10px);
  border-bottom-color: rgba(237, 230, 218, 0.13);
}

/* ============ Hero ============ */
.hero {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(120% 90% at 78% 110%, rgba(190, 90, 56, 0.34), transparent 55%),
    radial-gradient(90% 70% at 15% -10%, rgba(74, 99, 96, 0.35), transparent 60%),
    var(--ember-black);
  color: var(--bone);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: min(88vh, 780px);
  /* Photography goes here: replace the gradients with a full-bleed image
     or a short loop — steam, low warm light, someone stepping into Vättern. */
}
.hero::after {
  /* film-grain texture so the gradient placeholder doesn't read flat */
  content: "";
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E");
  pointer-events: none;
}
.hero h1 { max-width: 14ch; }
.hero .lede { margin-top: 1.2rem; }
.hero-actions .btn-quiet { color: var(--bone); opacity: 0.85; }
.hero-actions .btn-quiet:hover { opacity: 1; }

/* ============ Cinematic hero (home) ============
   Full-bleed sauna photograph, centred editorial type, warm gold wordmark.
   Swap the <img> in .hero-media for a <video> loop later — same box. */
/* column flex: justify-content is the vertical axis here, align-items the
   horizontal one — the block centres vertically, the type sets left */
.hero-cinematic {
  min-height: 100vh;
  min-height: 100svh;
  align-items: center;
  /* The copy is not centred in the frame. The photograph's backrest edge
     falls at 51% of the source height, and object-position below keeps it
     near 51% of the hero at every viewport shape — so the line under the
     headline is anchored to it, and the headline stacks upward from there
     onto the lit wall. See .hero-cine-inner. */
  justify-content: flex-start;
  text-align: left;
  padding: 0;
}
.hero-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}
.hero-media img,
.hero-media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Centred, not biased to the top. With cover, the crop's vertical offset is
     what decides where the benches land, and it moves with the viewport's
     shape: at 40% the bench line sat at 51% of the hero on a phone but slid to
     63% on a wide, short screen, which is a different picture and a different
     place for the type to sit. At 50% it stays within a point or two of 51%
     from 390px to ultrawide. */
  object-position: center 50%;
  /* slow, barely-there drift gives a still photo a breathing, alive feel */
  animation: hero-drift 26s ease-in-out infinite alternate;
}
@keyframes hero-drift {
  from { transform: scale(1.06) translate3d(0, 0, 0); }
  to   { transform: scale(1.14) translate3d(0, -1.5%, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-media img, .hero-media video { animation: none; }
}
/* Darken for legible type. On a phone the copy runs the full width, so a
   left-to-right ramp would just flatten the whole frame — the vertical
   gradient alone does the work, and the photograph keeps its light. */
.hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  /* The clear window sits in the top third, above the copy; from the middle
     down it deepens, because that is where the headline, the lede and the
     buttons are. */
  background: linear-gradient(
    180deg,
    rgba(20, 16, 13, 0.5) 0%,
    rgba(20, 16, 13, 0.18) 20%,
    rgba(20, 16, 13, 0.5) 55%,
    rgba(20, 16, 13, 0.74) 100%
  );
}
/* From tablet up the headline occupies the left third only, so the scrim
   weights that side and lets the right of the picture stay bright. */
@media (min-width: 820px) {
  .hero-media::after {
    background:
      linear-gradient(90deg, rgba(20, 16, 13, 0.66) 0%, rgba(20, 16, 13, 0.42) 34%, rgba(20, 16, 13, 0.1) 68%, rgba(20, 16, 13, 0.22) 100%),
      linear-gradient(180deg, rgba(20, 16, 13, 0.45) 0%, rgba(20, 16, 13, 0.08) 30%, rgba(20, 16, 13, 0.28) 70%, rgba(20, 16, 13, 0.62) 100%);
  }
}
/* THE ANCHOR. This box's top edge is the bench line: 53svh, a hair below the
   benches' top edge at 51%, and expressed in svh because the hero is 100svh
   so it reads as "53% of the frame".

   What lines up with it is the LEDE — the line under the headline — not the
   headline itself. That is why the headline is taken out of the flow below
   and hung above this edge instead: it is two lines on a desktop and can be
   three on a narrow phone, and any padding that positioned the block as a
   whole would put the lede in a different place at each size. Hanging the
   headline upward makes its height stop mattering. */
.hero-cine-inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--max-w);
  margin: 53vh auto 0;
  /* max(), because the headline hangs UPWARD from this line and a landscape
     phone does not leave it room: at 844×390 the bench falls at 53svh = 207px
     and the two headline lines above it need 235, so it slid under the fixed
     header. The floor is the header plus enough for the tallest the headline
     gets. Portrait and desktop are nowhere near it and keep the bench
     alignment exactly; a short landscape screen sits the copy a little below
     the bench edge instead of tucking it out of sight. */
  margin-top: max(53svh, calc(var(--header-h) + 11rem));
  padding: 0 var(--pad);
}
.hero-headline {
  /* Hung above the anchor rather than sitting in the flow — see
     .hero-cine-inner. bottom: 100% puts its bottom edge on the anchor line,
     and the margin below lifts it clear by the gap the lede used to carry as
     its own margin-top. Its height, and its line count, stop affecting where
     anything else lands. */
  position: absolute;
  left: var(--pad);
  right: var(--pad);
  bottom: 100%;
  margin: 0 0 1.5rem;
  font-family: var(--font-display);
  /* Like .hero-lede below, the headline may set its own line break: i18n
     writes it with textContent, so a \n in the locale only lands as a break
     because of this. The English wraps on its own and carries no \n. */
  white-space: pre-line;
  font-weight: 300;
  color: var(--bone);
  font-size: clamp(2.9rem, 8.4vw, 6.4rem);
  line-height: 0.99;
  letter-spacing: -0.012em;
  text-shadow: 0 2px 40px rgba(20,16,13,0.5);
}
/* Out-specifies the generic `.hero h1 { max-width: 14ch }`. The headline no
   longer fits one line in either language — "Din oas i vardagen" measures
   ~15ch and "Your oasis in everyday life" ~22ch — so this width picks where
   the second line starts instead of preventing one. 14ch breaks the Swedish
   after "i" and the English after "in", keeping a full phrase on each line;
   widening it to hold the English on one line would set it at a size that
   swamps the lede. A phone wraps the English to three lines on the container,
   which is the right place to wrap. */
.hero .hero-headline { max-width: 14ch; }
.hero-lede {
  color: var(--bone);
  /* The hero lede is the one string that sets its own line break: i18n
     writes it with textContent, so a \n in the locale only lands as a break
     because of this. Wrapping still happens normally within each line. */
  white-space: pre-line;
  font-size: clamp(1rem, 1.5vw, 1.13rem);
  line-height: 1.55;
  /* The \n gives this two lines, and this width exists to stop a third:
     50ch wrapped the English first line mid-phrase ("…sauna on the / shore
     of Lake Vättern"). That line is the longest either language has, at
     ~70ch, and 72ch holds it whole from about 900px up — narrower than that
     the container wraps it, which is the right place to wrap. */
  max-width: 72ch;
  /* The gap above lives on the headline now, which carries it as a
     margin-bottom while hanging off the anchor line. */
  margin: 0;
  opacity: 0.92;
  text-shadow: 0 1px 20px rgba(20,16,13,0.45);
}
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  margin-top: 2.3rem;
}
.hero-actions .btn {
  text-transform: uppercase;
  letter-spacing: 0.17em;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.95rem 1.7rem;
  border-radius: 3px;
}
/* On a phone the two buttons don't fit a row at desktop padding, and one
   stacked under the other reads as two ragged blocks. Let them share the
   row instead: equal halves, full thumb height, nothing wrapped. */
@media (max-width: 480px) {
  .hero-actions { gap: 0.6rem; flex-wrap: nowrap; }
  .hero-actions .btn {
    flex: 1 1 0;
    min-width: 0;
    padding-left: 0.6rem;
    padding-right: 0.6rem;
    letter-spacing: 0.1em;
  }
}
/* bottom band: scroll cue */
.hero-foot {
  position: absolute;
  z-index: 1;
  bottom: clamp(1.6rem, 4vh, 2.6rem);
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.1rem;
  padding: 0 var(--pad);
  text-align: center;
}
.scroll-cue {
  width: 20px;
  height: 20px;
  border-right: 1.5px solid rgba(237, 230, 218, 0.8);
  border-bottom: 1.5px solid rgba(237, 230, 218, 0.8);
  transform: rotate(45deg);
  animation: scroll-bob 2.2s ease-in-out infinite;
}
@keyframes scroll-bob {
  0%, 100% { transform: rotate(45deg) translate(0, 0); opacity: 0.55; }
  50%      { transform: rotate(45deg) translate(4px, 4px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) { .scroll-cue { animation: none; } }

/* ============ Showcase — the one full-bleed photograph ============
   Type set over the image, so the scrim is load-bearing: it is the only
   thing keeping the copy at a readable contrast on a bright frame. */
.showcase {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: min(78svh, 640px);
  padding: clamp(3rem, 10vw, 6rem) 0;
  overflow: hidden;
  background: var(--ember-black);
  color: var(--bone);
}
.showcase-media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 35%;
}
.showcase::after {
  content: "";
  position: absolute;
  inset: 0;
  /* Two gradients, both doing work: the vertical one weights the bottom,
     where the type is; the horizontal one darkens the left, where the type
     starts, so a bright frame can't swallow the first words of a line. */
  background:
    linear-gradient(90deg, rgba(20, 16, 13, 0.55) 0%, rgba(20, 16, 13, 0.2) 55%, transparent 85%),
    linear-gradient(180deg, rgba(20, 16, 13, 0.3) 0%, rgba(20, 16, 13, 0.42) 35%, rgba(20, 16, 13, 0.9) 100%);
}
.showcase-inner { position: relative; z-index: 1; width: 100%; }
.showcase-inner .kicker { color: var(--gold); }
/* Wide enough that "Värme. Kyla. Vila. Om igen." holds one line on a desktop.
   At 18ch it broke after "Om" and left "igen." alone on the second line, which
   is the worst of the available breaks. `balance` picks an even one where the
   line still has to wrap, on a phone. The band carries only the heading now,
   so there is nothing under it competing for the width. */
.showcase-inner h2 { max-width: 30ch; text-wrap: balance; }
.showcase-inner .lede { margin-top: 1.2rem; max-width: 52ch; opacity: 1; }
.showcase-inner .feature-cta { margin-top: 2rem; }

/* The same full-bleed band on Om oss, shorter, carrying the slogan. It used
   to hold a pull quote; a slogan is the thing the page is named after, so it
   is set larger than that quote was. */
.about-showcase { min-height: min(58svh, 500px); align-items: center; }
.showcase-quote {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(1.9rem, 4.8vw, 3.2rem);
  line-height: 1.15;
  letter-spacing: -0.022em;
  max-width: 20ch;
  text-wrap: balance;
  margin: 0;
}

/* ============ About page ============
   The page used to start on a bare paragraph. It opens on a heading now,
   with the first line set large and the rest running in two columns so a
   wide screen doesn't stretch the prose past a readable measure. */
/* One column, not two. The two-column split was there to keep a long
   three-paragraph story off a wide screen's full width; with the story down
   to two paragraphs it just cut a short text in half. */
.about-text { margin-top: 1.4rem; max-width: 64ch; }

/* ============ The ritual text section — DORMANT ============
   NO PAGE MOUNTS [data-ritual-body]. The start page carries the four-sentence
   summary over the photograph instead, which says the ritual better than the
   eight paragraphs did. Everything below is kept and working: restoring the
   section is one <section class="section ritual"> holding a
   <div class="ritual-flow" data-ritual-body></div>, and nothing else.

   The passage between two dark bands: the photograph above it and the footer
   below. Keeping it on bone makes it a clearing rather than a continuation,
   which is the shape of the thing it describes.

   THE RAIL IS A THERMOMETER. A gold hairline runs the height of the text,
   fading in and out at both ends, with a graduation mark beside every
   paragraph and a filled bead closing the scale at the last one. The ritual
   is a sequence of temperature states, so the ornament is the subject.

   Only :first-child and :last-child carry special treatment. Nothing keys off
   an nth paragraph, so the opening line and the coda keep their shape however
   many paragraphs the locale grows to. */
.ritual {
  position: relative;
  overflow: hidden;
}
/* Heat coming off the band above, spilling a little way down the page. Sits
   under the text (z-index) and ignores the pointer. */
.ritual::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 70%;
  /* Two stops rather than one: the gold alone washed out to nothing against
     bone at any alpha subtle enough to stay tasteful. A touch of the ember
     clay under it gives the warmth somewhere to sit, so the top of the
     section reads as still holding heat from the band above. */
  background:
    radial-gradient(120% 92% at 50% 0%, rgba(190, 90, 56, 0.09), transparent 68%),
    radial-gradient(105% 80% at 50% 0%, rgba(215, 172, 103, 0.38), transparent 70%);
  pointer-events: none;
}
.ritual .container { position: relative; }

.ritual-flow {
  position: relative;
  max-width: 62ch;
  padding-left: 1.9rem;
}
/* The rail. A gradient rather than a flat rule so it does not start and stop
   with two hard ends, which would read as a border. */
.ritual-flow::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6rem;
  bottom: 0.6rem;
  width: 1px;
  background: linear-gradient(
    180deg,
    transparent 0%,
    rgba(215, 172, 103, 0.75) 10%,
    rgba(215, 172, 103, 0.75) 86%,
    transparent 100%
  );
}
.ritual-flow p {
  position: relative;
  font-size: 1.01rem;
  line-height: 1.85;
  color: var(--ember-black);
  opacity: 0.82;
}
.ritual-flow p + p { margin-top: 1.75rem; }
/* A graduation on the scale, level with the first line of its paragraph. */
.ritual-flow p::before {
  content: "";
  position: absolute;
  left: -1.9rem;
  top: 0.85em;
  width: 0.95rem;
  height: 1px;
  background: var(--gold);
  opacity: 0.85;
}

/* The opening line: the invitation, set in the display register and given a
   short measure so it breaks over two or three lines and reads as a statement
   rather than as the first of eight paragraphs. */
.ritual-flow p:first-child {
  font-weight: 200;
  font-size: clamp(1.3rem, 3.1vw, 1.85rem);
  line-height: 1.32;
  letter-spacing: -0.02em;
  max-width: 26ch;
  opacity: 1;
  margin-bottom: 2.3rem;
}
.ritual-flow p:first-child::before { top: 0.62em; }

/* The coda. Set apart, in the display register, and closing the scale with a
   filled bead where the other paragraphs have a dash. */
.ritual-flow p:last-child {
  margin-top: 2.7rem;
  font-weight: 300;
  font-size: clamp(1.12rem, 2.4vw, 1.45rem);
  line-height: 1.45;
  letter-spacing: -0.015em;
  max-width: 30ch;
  opacity: 1;
}
.ritual-flow p:last-child::before {
  left: calc(-1.9rem - 2px);
  top: 0.62em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--gold);
  opacity: 1;
}
/* One paragraph is both the opening and the coda; the opening wins, and the
   bead would otherwise sit on a line it does not close. */
.ritual-flow p:first-child:last-child { margin-top: 0; }

@media (min-width: 900px) {
  /* Indented from the container edge the rest of the page starts at, so the
     passage reads as set apart from the page rather than as another column
     of it. */
  .ritual-flow { margin-left: clamp(0rem, 7vw, 6rem); padding-left: 2.4rem; }
  .ritual-flow p::before { left: -2.4rem; width: 1.3rem; }
  .ritual-flow p:last-child::before { left: calc(-2.4rem - 2px); }
}

/* Each paragraph rises as it comes into view. Progressive: browsers without
   scroll-driven animations simply show the text, which is the point of the
   section. Silenced entirely for anyone who asked for less motion. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .ritual-flow p {
      opacity: 0;
      animation: ritual-rise linear both;
      animation-timeline: view();
      animation-range: entry 5% cover 22%;
    }
    /* The special-cased paragraphs settle at full strength, the rest at the
       reading opacity they are set in above. */
    @keyframes ritual-rise {
      from { opacity: 0; transform: translateY(1.1rem); }
      to   { opacity: 0.82; transform: none; }
    }
    .ritual-flow p:first-child,
    .ritual-flow p:last-child { animation-name: ritual-rise-full; }
    @keyframes ritual-rise-full {
      from { opacity: 0; transform: translateY(1.1rem); }
      to   { opacity: 1; transform: none; }
    }
  }
}




.about-text p + p { margin-top: 1.2rem; }
.about-lead { margin-top: 0; max-width: none; }
@media (min-width: 820px) { .about-open h2 { max-width: 20ch; } }

/* ============ Membership block (home) ============
   One column: kicker, heading, one paragraph, two buttons. It ran as a
   two-column split with the price on the right and a list of what a
   membership includes under it; the price came off by request and the column
   went with it, because half a split is just an indent.

   The measure is what stops the paragraph running the container's full
   1040px — a 100-character line is unreadable however good the type is. */
.mem-lead .lede { margin-top: 1.1rem; max-width: 62ch; }
@media (min-width: 820px) { .mem-lead h2 { max-width: 24ch; } }

/* DORMANT — the price panel, mounted on no page.
   `[data-mana-from]` and its renderFromPrice in mana-views.js are both still
   here and still work; nothing calls them. These are the styles that dressed
   the result, kept in step with the view so restoring the price is markup and
   nothing else: a <p class="mem-from" data-mana-from> back in a
   <aside class="mem-panel">, plus mana.js and mana-views.js on the page.
   .mem-panel's right-alignment above 820px went with the two-column layout;
   put it back with the column if the split ever returns. */
.mem-panel { padding-top: 0.4rem; }
.mem-from {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0;
}
.mem-from-label {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.6;
}
.mem-from-amount {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(2.1rem, 5vw, 2.7rem);
  letter-spacing: -0.03em;
  line-height: 1;
}
.mem-from-period { font-size: 0.9rem; opacity: 0.6; }
/* Not dormant: sallskap-foretag.html borrows this list outright (.corp-incl
   sits on top of it) rather than growing a second one. */
.mem-incl { list-style: none; display: grid; gap: 0; }
.mem-incl li {
  padding: 0.85rem 0;
  font-size: 0.97rem;
  border-bottom: 1px solid rgba(32, 27, 23, 0.12);
}
.mem-incl li:first-child { border-top: 1px solid rgba(32, 27, 23, 0.12); }

/* ============ Groups & companies ============
   One centred column: what the offer is, then the form to ask for it. The
   page used to run a two-column opening, a letterboxed photograph and a
   two-column "Det ingår" block before the form appeared — a lot of page for
   an offer that is one sentence long. It borrows the membership block's
   list outright (.mem-incl) rather than growing a second one, and carries
   no ember button anywhere so it can never out-shout Bli medlem. */
/* .centered's 760px is a measure for prose, and it breaks the headline
   across two lines to leave "ert" alone on the second. The column runs a
   little wider here; the prose inside keeps its own 62ch cap regardless. */
.centered.corp .container { max-width: 880px; }
/* Short centred type strands its last word on a line of its own. Balance
   evens the lines out; browsers without it just wrap as before. */
.corp h2, .corp .lede { text-wrap: balance; }
/* The opening statement carries the page alone now, so it sits a step below
   a full heading and well above the line under it: the first thing read,
   without becoming a banner. */
.corp-open-line {
  font-size: clamp(1.65rem, 3.4vw, 2.5rem);
  font-weight: 300;
  letter-spacing: -0.018em;
  line-height: 1.2;
  max-width: 26ch;
  margin-left: auto;
  margin-right: auto;
}
.corp-open-line + .lede { margin-top: 1.5rem; }
/* p sets its own 62ch measure and no auto margins, so prose in a centred
   column would sit left of centre without this. Direct children only — the
   form's fine print is a p too, and it belongs on the form's left edge, not
   floated into the middle of its row. */
.corp .container > p { margin-left: auto; margin-right: auto; }

/* The label above the list. Kicker type, but deliberately without the gold
   rule .centered .kicker draws — that device opens the page, and spending
   it twice on one screen makes neither instance mean anything. */
.corp-incl-label {
  margin-top: clamp(2.75rem, 6vw, 4rem);
  margin-bottom: 1.1rem;
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--slate);
}
/* A short measure so the four lines read as a list rather than as four full
   -width rules across the column. */
.corp-incl { max-width: 42ch; margin-left: auto; margin-right: auto; }

.corp-price { margin-top: 1.6rem; font-size: 0.95rem; opacity: 0.75; }

/* The form is the second half of the same section, far enough below the
   offer to read as the next move rather than more of the same sentence. */
.centered .corp-ask { margin-top: clamp(3.25rem, 8vw, 5.5rem); }
/* Centred editorial, but a form is not prose: fields go back to left so the
   labels sit above their inputs. Same reasoning as .interest-form. */
.corp-form { max-width: 700px; margin: 2.2rem auto 0; text-align: left; }
.corp-form .form-note { margin-top: 0.8rem; }
@media (max-width: 560px) {
  /* The one action on the screen — give it the full thumb target. */
  .corp-form .btn { display: block; width: 100%; }
}

/* ============ Place ============ */
.place { border-top: 1px solid rgba(32, 27, 23, 0.12); }
.place-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.4rem 2rem;
}
.place-title { font-size: clamp(1.5rem, 3.5vw, 2.1rem); }
.place-address { margin-top: 0.5rem; opacity: 0.75; }
.place-note { margin-top: 0.25rem; font-size: 0.9rem; opacity: 0.55; }

/* ============ Temperature strip ============ */
.temp-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.6rem 0.9rem;
  font-size: 0.95rem;
  font-variant-numeric: tabular-nums;
}
.temp-item { display: inline-flex; align-items: baseline; gap: 0.45rem; }
.temp-label { font-size: 0.78rem; font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase; opacity: 0.75; }
.temp-value { font-family: var(--font-display); font-size: 1.5rem; font-weight: 600; line-height: 1; }
.temp-sauna .temp-value { color: var(--ember); }
.temp-air .temp-value { color: var(--gold); }
.temp-water .temp-value { color: var(--slate); }
/* Vättern is a fortnightly sample, not a live feed, so it carries the date
   it was taken — quietly, at the size of a footnote. */
.temp-note { font-size: 0.72rem; opacity: 0.5; letter-spacing: 0.04em; }
.temp-strip-lg .temp-note { font-size: 0.8rem; }
.dark .temp-water .temp-value,
.hero .temp-water .temp-value { color: #8fb0ab; } /* slate lifted for dark ground */
.temp-item.is-stale { opacity: 0.55; }
.temp-updated { font-size: 0.8rem; opacity: 0.6; }
.temp-sep { opacity: 0.35; }

/* strip band under the hero */
.temp-band {
  background: var(--ember-black);
  color: var(--bone);
  border-top: 1px solid rgba(237, 230, 218, 0.12);
}
.temp-band .container { padding-top: 1rem; padding-bottom: 1rem; }

/* larger variant (experience page) */
.temp-strip-lg { gap: 1.2rem 2rem; }
.temp-strip-lg .temp-value { font-size: clamp(2.6rem, 7vw, 4rem); }
.temp-strip-lg .temp-updated { flex-basis: 100%; }

/* ============ Scarcity ============ */

/* ============ Content blocks ============ */
.grid { display: grid; gap: 1.2rem; }
@media (min-width: 700px) {
  .grid-2 { grid-template-columns: 1fr 1fr; }
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
  .grid-4 { grid-template-columns: repeat(4, 1fr); }
}

.card {
  background: var(--sand);
  padding: 1.8rem 1.6rem;
  border-radius: var(--radius);
}
.card h3 { margin-bottom: 0.5rem; }
.card p { font-size: 0.95rem; opacity: 0.9; }

.steps { counter-reset: step; }
.step { position: relative; padding-top: 2.6rem; }
.step::before {
  counter-increment: step;
  content: counter(step, decimal-leading-zero);
  position: absolute;
  top: 0;
  font-family: var(--font-display);
  font-size: 1.1rem;
  color: var(--ember);
}
.step h3 { font-size: 1.15rem; margin-bottom: 0.35rem; }
.step p { font-size: 0.95rem; opacity: 0.85; }

/* Centred editorial sections — a thin gold rule, generous measure.
   Used for the membership feature and the groups/companies band. */
.centered { text-align: center; }
.centered .container { max-width: 760px; }
.centered .lede { margin-left: auto; margin-right: auto; }
.centered .kicker { color: var(--ember); }
.centered .kicker::before,
.centered-head::before {
  content: "";
  display: block;
  width: 42px;
  height: 2px;
  background: var(--gold);
  margin: 0 auto 1.3rem;
}
.centered h2 { margin-top: 0.2rem; }
.centered .lede { margin-top: 1.2rem; }

/* Centred heading only (how-it-works keeps its left-aligned numbered steps) */
.centered-head { text-align: center; max-width: 720px; margin: 0 auto; }

.feature-cta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0.8rem 1.4rem;
  margin-top: 2.2rem;
}
.feature-cta .btn-quiet { color: var(--ember-black); }
.feature-cta.start { justify-content: flex-start; }

.split { display: grid; gap: 2.5rem; align-items: center; }
@media (min-width: 820px) { .split { grid-template-columns: 1fr 1fr; gap: 4rem; } }

/* photo placeholders — swap for real photography */
.photo {
  border-radius: var(--radius);
  min-height: 320px;
  background:
    radial-gradient(90% 90% at 70% 100%, rgba(190, 90, 56, 0.3), transparent 60%),
    radial-gradient(70% 60% at 10% 0%, rgba(74, 99, 96, 0.4), transparent 60%),
    linear-gradient(160deg, #2b2620, var(--ember-black));
}
.photo-tall { min-height: 440px; }

/* Sales-pitch photo (home) — real image on the right, fills its column */
.split-text .pitch-media { align-self: stretch; }
.pitch-media {
  border-radius: var(--radius);
  overflow: hidden;
  min-height: clamp(300px, 42vh, 460px);
}
.pitch-media img { width: 100%; height: 100%; object-fit: cover; }

/* Instagram — icon links (header/footer) + the follow button (home band) */
.ig-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  opacity: 0.85;
  text-decoration: none;
  transition: opacity 0.15s ease;
}
.ig-link:hover { opacity: 1; }
.ig-glyph { display: block; flex-shrink: 0; }
.ig-row { font-size: 0.9rem; }
.nav-extra .ig-link { font-size: 1rem; opacity: 1; }

/* Prose sections (about) */
.prose p + p { margin-top: 1.2rem; }
.prose p { font-size: clamp(1rem, 2vw, 1.15rem); }

/* Price block */
.price-block { text-align: center; }
.price-figure {
  font-family: var(--font-display);
  font-size: clamp(3rem, 9vw, 5rem);
  font-weight: 600;
  line-height: 1;
}
.price-period { display: block; margin-top: 0.4rem; opacity: 0.7; }

/* Closing block under the steps — back to the plans, and where the fine
   print went once the rules section came off this page */
/* The closing fine print. It used to stack a section's padding, its own
   top margin and a padding-top on the rule — three gaps doing one gap's
   job, which is most of what read as dead space on this page. */
.mem-help { text-align: center; }
/* A section of its own, not a subsection of the form above it — so an h2,
   sized down to the quiet thing it is. */
.mem-help h2 {
  font-size: clamp(1.25rem, 2.4vw, 1.5rem);
  margin-bottom: 0.5rem;
}
.mem-help p { margin: 0 auto; opacity: 0.8; max-width: 52ch; }
.mem-help .feature-cta { margin-top: 1.6rem; }
/* Two quiet links share a row with the button instead of being two more
   buttons — three equal buttons wrapped 2 + 1 on a phone. */
.help-links { display: inline-flex; flex-wrap: wrap; gap: 0.4rem 1.4rem; align-items: center; }
.help-links a {
  font-size: 0.9rem;
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 4px;
  opacity: 0.7;
}
.help-links a:hover { opacity: 1; }


/* Rules / facts list */
.rule-list { display: grid; gap: 0; border-top: 1px solid rgba(32, 27, 23, 0.15); }
.rule-item { padding: 1.4rem 0; border-bottom: 1px solid rgba(32, 27, 23, 0.15); }
.rule-item h3 { font-size: 1.05rem; font-family: var(--font-body); font-weight: 600; margin-bottom: 0.3rem; }
.rule-item p { font-size: 0.95rem; opacity: 0.85; }
@media (min-width: 700px) {
  .rule-item { display: grid; grid-template-columns: 220px 1fr; gap: 2rem; }
  .rule-item h3 { margin-bottom: 0; }
}

/* Accordion (FAQ) */
.accordion-item { border-bottom: 1px solid rgba(32, 27, 23, 0.15); }
.accordion-item > button {
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  text-align: left;
  padding: 1.3rem 0;
  font-weight: 600;
  font-size: 1.02rem;
}
.accordion-item > button::after {
  content: "+";
  font-family: var(--font-display);
  font-size: 1.4rem;
  color: var(--ember);
  transition: transform 0.2s ease;
  flex-shrink: 0;
}
.accordion-item.is-open > button::after { transform: rotate(45deg); }
.accordion-body { display: none; padding: 0 0 1.4rem; opacity: 0.85; }
/* Answers are plain prose apart from one hand-off link, which needs to look
   like a link — everything else on the site inherits its colour. */
.accordion-body a { text-decoration: underline; text-underline-offset: 3px; }
.accordion-item.is-open .accordion-body { display: block; }

/* Forms */
.form-grid { display: grid; gap: 1rem; }
@media (min-width: 700px) { .form-grid { grid-template-columns: 1fr 1fr; } }
.form-grid .full { grid-column: 1 / -1; }
label { display: block; font-size: 0.82rem; font-weight: 600; letter-spacing: 0.04em; margin-bottom: 0.35rem; }
input, textarea {
  width: 100%;
  font: inherit;
  padding: 0.75rem 0.9rem;
  border: 1px solid rgba(32, 27, 23, 0.3);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, 0.45);
  color: var(--ember-black);
}
input:focus, textarea:focus { outline: 2px solid var(--slate); outline-offset: 1px; }
.form-note { font-size: 0.82rem; opacity: 0.65; }

/* select is styled to match input/textarea; appearance:none strips the OS
   chrome so the caret below is the only one drawn. */
select {
  width: 100%;
  font: inherit;
  padding: 0.75rem 2.4rem 0.75rem 0.9rem;
  border: 1px solid rgba(32, 27, 23, 0.3);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, 0.45);
  color: var(--ember-black);
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%23201b17' stroke-width='1.6'%3E%3Cpath d='m1 1.5 5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.9rem center;
}
select:focus { outline: 2px solid var(--slate); outline-offset: 1px; }

/* Interest form — the conversion point of the site until checkout opens.
   The section is centred editorial, but a form is not prose: the fields go
   back to left-aligned so labels sit above their inputs. */
.interest-form { margin-top: 2.5rem; text-align: left; }

/* --- The dark band it sits in ----------------------------------------
   Form controls default to dark ink on a light fill, which is invisible on
   ember black. Everything below re-grounds them: fields, the select caret,
   the labels and the fine print. */
/* The band opens straight on its heading now that the kicker and its gold
   rule are gone, so it does not need a full section's padding above: that
   was sized for a line of type that is no longer there. */
.interest-band { padding-top: clamp(2.75rem, 6.5vw, 5rem); }
/* The second half of the form's standfirst — the sentence that says nothing
   is binding. Quieter than the lede above it, but it has to be readable: it
   is the line that decides whether someone types their email. */
.interest-sub2 {
  max-width: 56ch;
  margin: 0.9rem auto 0;
  font-size: 0.95rem;
  opacity: 0.75;
}
.interest-band label { opacity: 0.8; }
.interest-band input,
.interest-band textarea,
.interest-band select {
  /* background-color, never the `background` shorthand: the shorthand would
     reset background-repeat and -position, and the select's caret image
     would tile across the whole control instead of sitting at its right. */
  background-color: rgba(237, 230, 218, 0.07);
  border-color: rgba(237, 230, 218, 0.28);
  color: var(--bone);
}
.interest-band input:hover,
.interest-band textarea:hover,
.interest-band select:hover { border-color: rgba(237, 230, 218, 0.45); }
.interest-band input:focus,
.interest-band textarea:focus,
.interest-band select:focus { outline-color: var(--gold); }
.interest-band ::placeholder { color: rgba(237, 230, 218, 0.4); }
/* The caret is a background image with a baked-in stroke colour, so the
   dark ground needs its own copy in bone. */
.interest-band select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%23ede6da' stroke-width='1.6'%3E%3Cpath d='m1 1.5 5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.9rem center;
}
/* A native dropdown paints its own list; on macOS and Windows that list
   inherits the control's colours, so the options need a ground of their own
   or they arrive as bone text on white. */
.interest-band select option { background: var(--ember-black); color: var(--bone); }
.interest-band .form-note { opacity: 0.6; }
.interest-band .form-note a { color: var(--sand); }
.interest-band .interest-done {
  background: rgba(215, 172, 103, 0.1);
  border-left-color: var(--gold);
}
/* Full-width submit on a phone: it is the one action on the screen and the
   easiest possible thumb target. */
@media (max-width: 640px) {
  .interest-form button[type="submit"] { width: 100%; }
}
/* Honeypot — off-screen rather than display:none, because some bots skip
   fields they can tell are hidden. Nothing here is reachable by tab. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.interest-note { margin-top: 0.9rem; max-width: none; }
/* While the request is in flight the button reads as busy, so nobody
   double-submits into the duplicate guard and wonders why nothing happened. */
.interest-form.is-sending button[type="submit"] { opacity: 0.55; cursor: progress; }

.interest-done {
  margin: 1.6rem auto 0;
  max-width: 52ch;
  padding: 1rem 1.2rem;
  border-left: 2px solid var(--gold);
  background: rgba(215, 172, 103, 0.12);
  text-align: left;
  font-size: 0.95rem;
}

/* ============ Mana ============
   Plans, bundles and shop items are our own cards drawn from Mana's live
   API — only the schedule is Mana's own widget. Every action inside them
   leaves for Mana: checkout, sign-in and accounts are never rebuilt here. */

.mana-grid {
  display: grid;
  gap: 1.2rem;
  margin-top: 2.5rem;
  text-align: left;
}
@media (min-width: 760px) {
  /* auto-fit, not a fixed count: Mana decides how many plans exist, and the
     row re-forms itself when one is added or retired. */
  .mana-grid-plans { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
  /* One plan is a card, not a banner. auto-fit gives a lone item the whole
     1040px row, which reads as an empty box with a price in one corner — and
     one plan is the normal state right now, with Oas Member hidden (see
     config.hiddenMembershipIds). Two or more and this rule does nothing. */
  .mana-grid-plans:has(> .mana-card:only-child) { max-width: 420px; }
  /* auto-fill, not auto-fit, so a lone product stays a card instead of
     stretching across the whole row. */
  .mana-grid-shop { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
}

/* ============ Membership page: the membership, alone ============
   No kicker, no heading, no standfirst above it, so the card has to hold the
   top of the page by itself. It gets room to breathe, a little more size, and
   a gap wide enough that several of them would read as several objects rather
   than as a striped band.

   The card is CENTRED here, not left-aligned like the plans grid elsewhere:
   with nothing above it to share a left edge with, a card hard against the
   container's left margin reads as the leftover of a row rather than as the
   one thing the page is for. :has() keeps that to the single-card case — put
   Oas Member back (config.hiddenMembershipIds) and the row goes back to
   filling the container from the left. */
body[data-page="membership"] .plans-only {
  padding-top: clamp(3.25rem, 7vw, 5.5rem);
}
.plans-only .mana-grid { margin-top: 0; }
.plans-only .mana-grid-plans:has(> .mana-card:only-child) { margin-inline: auto; }
/* The plans section used to close with its own full .section padding, and the
   fine-print section under it opened with more — up to 10rem of nothing
   between the prices and "Frågor?". The cards now end the section, so it stops
   padding the bottom and the section below supplies the whole gap. */
.plans-only { padding-bottom: 0; }
@media (min-width: 760px) {
  .plans-only .mana-grid-plans { gap: 1.6rem; }
  .plans-only .mana-card { padding: 2.4rem 2rem 2rem; }
  .plans-only .mana-amount { font-size: clamp(2.5rem, 5.2vw, 3.1rem); }
}

.mana-card {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  /* A warm off-white on the bone ground, with a hairline instead of a fill.
     The old sand-on-bone was two close warm tones with nothing between them,
     so the cards read as smudges rather than as objects. */
  background: rgba(255, 253, 250, 0.62);
  border: 1px solid rgba(32, 27, 23, 0.1);
  border-radius: var(--radius);
  padding: 1.9rem 1.6rem 1.6rem;
}
.mana-card-title {
  font-family: var(--font-body);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--slate);
}
/* The price is the headline of a pricing card, so it gets the display size
   and the plan name steps back to a label above it. */
.mana-price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin: 0.35rem 0 0;
}
.mana-amount {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(2.3rem, 5vw, 2.9rem);
  letter-spacing: -0.03em;
  line-height: 1;
}
.mana-period { font-size: 0.9rem; opacity: 0.6; }
.mana-was { font-size: 0.95rem; opacity: 0.5; }
.mana-meta {
  font-size: 0.9rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ember-black);
  opacity: 0.85;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid rgba(32, 27, 23, 0.1);
}
.mana-desc { font-size: 0.92rem; opacity: 0.7; line-height: 1.6; }

/* --- Card head, and the collapse on a phone ----------------------------
   The button carries the plan name and, when the card is collapsible, the
   chevron. It is styled to disappear into the heading it sits in: above the
   plans breakpoint there is nothing to press and the card is simply a card.

   Everything hides on .is-collapsible, a class main.js puts on, rather than
   on a media query here — one source of truth for "can this card shut", so
   the stylesheet and the script cannot drift apart. */
.mana-card-toggle {
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  text-align: left;
  cursor: default;
}
.mana-card.is-collapsible .mana-card-toggle { cursor: pointer; }
.mana-card-toggle:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }
.mana-card-chevron {
  display: none;
  flex: none;
  width: 8px;
  height: 8px;
  margin-bottom: 3px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform 0.25s ease;
  opacity: 0.75;
}
.mana-card.is-collapsible .mana-card-chevron { display: block; }
.mana-card.is-collapsible.is-open .mana-card-chevron {
  transform: rotate(-135deg);
  margin-bottom: -3px;
}
/* A flex column of its own so .mana-actions' margin-top:auto still pushes the
   buttons to the floor of the card, which is what lines the actions up across
   a row of cards with copy of unequal length. */
.mana-card-body {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  flex: 1;
}
.mana-card.is-collapsible:not(.is-open) .mana-card-body { display: none; }
/* Shut, the card is a name and a price — so it loses the floor the buttons
   used to stand on. */
.mana-card.is-collapsible:not(.is-open) { padding-bottom: 1.4rem; }
/* The buttons sit on the floor of the card so cards of unequal copy length
   still line their actions up across the row. */
.mana-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.9rem;
  margin-top: auto;
  padding-top: 1.4rem;
}
.mana-actions .btn-quiet { color: var(--ember-black); }

/* An inert button: the shape of the real one, without the invitation. It is
   what stands where Köp will stand before launch, so the card keeps its floor
   and the row keeps one action line however long the copy runs. Flat, no
   hover, no pointer — everything that says "press me" is what comes off. */
.btn.is-disabled {
  background: rgba(32, 27, 23, 0.06);
  color: var(--ember-black);
  border: 1px solid rgba(32, 27, 23, 0.16);
  opacity: 0.8;
  cursor: default;
}
.btn.is-disabled:hover {
  background: rgba(32, 27, 23, 0.06);
  border-color: rgba(32, 27, 23, 0.16);
}
.dark .btn.is-disabled,
.member-mode .btn.is-disabled {
  background: rgba(237, 230, 218, 0.1);
  color: var(--bone);
  border-color: rgba(237, 230, 218, 0.28);
}

/* Trial offer — Mana's strongest conversion lever, so it gets a band of its
   own rather than a card, and vanishes entirely when no offer is live. */
.mana-trial {
  background: var(--ember-black);
  color: var(--bone);
  border-radius: var(--radius);
  padding: clamp(1.8rem, 5vw, 2.8rem);
  text-align: left;
}
.mana-trial .kicker { color: var(--gold); }
.mana-trial-title { font-size: clamp(1.6rem, 3.5vw, 2.2rem); }
.mana-trial-offers {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  margin-top: 1.6rem;
}
.mana-trial-offer {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  flex: 1 1 200px;
  padding: 1rem 1.2rem;
  border: 1px solid rgba(237, 230, 218, 0.35);
  border-radius: var(--radius);
  text-decoration: none;
  transition: border-color 0.2s ease, background 0.2s ease;
}
.mana-trial-offer:hover { border-color: var(--gold); background: rgba(215, 172, 103, 0.1); }
.mana-trial-name { font-size: 0.95rem; opacity: 0.85; }

/* Founding offer — same band as a trial, but it is the one thing on the page
   that can actually be bought before opening, so it gets room to breathe. */
.presale-body { margin-top: 1rem; max-width: 56ch; opacity: 0.85; }
.presale-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.8rem 1.4rem;
  margin-top: 1.8rem;
}
.presale-note { font-size: 0.82rem; opacity: 0.55; }
.mana-trial-price { font-family: var(--font-display); font-size: 1.5rem; font-weight: 300; }

/* Schedule — our own list, grouped by day. Rows are whole-row links into
   Mana's schedule, which is where booking actually happens. */
.mana-schedule { margin-top: 2rem; }
.mana-schedule-loading { opacity: 0.5; font-size: 0.9rem; }
.mana-schedule-empty {
  border: 1px dashed rgba(32, 27, 23, 0.3);
  border-radius: var(--radius);
  padding: clamp(2rem, 6vw, 3.5rem) 1.6rem;
  text-align: center;
}
.mana-schedule-empty p { margin: 0 auto 1.6rem; max-width: 48ch; opacity: 0.75; }
.member-mode .mana-schedule-empty { border-color: rgba(237, 230, 218, 0.25); }

.mana-day + .mana-day { margin-top: 2rem; }
.mana-day-label {
  font-size: 0.78rem;
  font-family: var(--font-body);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  opacity: 0.55;
  margin-bottom: 0.7rem;
}
.mana-day-list { list-style: none; display: grid; gap: 0.5rem; }

.mana-slot {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 0.4rem 1.2rem;
  padding: 1rem 1.2rem;
  border: 1px solid rgba(32, 27, 23, 0.14);
  border-radius: var(--radius);
  text-decoration: none;
  transition: border-color 0.2s ease, background 0.2s ease;
}
.mana-slot:hover { border-color: var(--slate); background: rgba(74, 99, 96, 0.06); }
.mana-slot-time {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 500;
  white-space: nowrap;
}
.mana-slot-end { opacity: 0.45; font-weight: 300; }
.mana-slot-main { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.mana-slot-title { font-size: 1rem; }
.mana-slot-seats { font-size: 0.82rem; opacity: 0.6; }
.mana-slot-cta {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--slate);
  white-space: nowrap;
}
/* A full session still links through — Mana carries the waitlist. */
.mana-slot.is-full { opacity: 0.62; }
.mana-slot.is-full .mana-slot-cta { color: var(--ember); }
.mana-schedule-foot { margin-top: 1.6rem; }

@media (max-width: 560px) {
  /* Time above the title, action on its own line — nothing truncates. */
  .mana-slot { grid-template-columns: 1fr auto; }
  .mana-slot-time { grid-column: 1 / -1; font-size: 1.05rem; }
}

.member-mode .mana-slot { border-color: rgba(237, 230, 218, 0.16); }
.member-mode .mana-slot:hover { border-color: var(--gold); background: rgba(237, 230, 218, 0.05); }
.member-mode .mana-slot-cta { color: var(--gold); }
.member-mode .mana-day-label { opacity: 0.5; }

/* ============ Experience: the four steps ============
   A full-height dark panel of four standing photographs, at most one open
   at a time — and none of them open when the page arrives, so the resting
   state is four equal rectangles that read as "pick one". Opening is
   therefore a real toggle: the "+" turns to an "×" and puts the row back.
   The whole thing is one flex row and one number: every card is
   `flex: 1`, the open one is `flex-grow: var(--exp-open)`, and animating
   that single property is what makes the others give way. Nothing is
   measured in JS — the layout is the animation.

   On a phone the same row turns into a column and the same flex-grow
   works on height instead, so there is one mechanism, not two.

   The card body is height-animated with the grid 0fr → 1fr trick, and its
   inner wrapper is given a fixed width so the copy does not re-wrap in a
   200px card on the way out; the card's overflow clips it. */
.exp-steps-band {
  --exp-w: 1440px;               /* wider than the site's 1120 — the panel is cinematic */
  --exp-open: 3.4;               /* how many collapsed cards the open one is worth */
  --exp-ease: cubic-bezier(0.4, 0, 0.2, 1);
  background:
    radial-gradient(90% 60% at 50% 120%, rgba(190, 90, 56, 0.16), transparent 65%),
    var(--ember-black);
  color: var(--bone);
  min-height: calc(100svh - var(--header-h));
  display: flex;
  flex-direction: column;
  gap: clamp(1.1rem, 2.6vw, 2rem);
  overflow: hidden;              /* the cards' own corners, never a stray scrollbar */
}
/* Beats the generic "interior pages open onto content" padding rule, which
   would otherwise wedge the panel down the screen. */
body[data-page="experience"] main > .exp-steps-band {
  padding: clamp(1.4rem, 3vw, 2.4rem) var(--pad) clamp(1.6rem, 3.5vw, 2.6rem);
}

.exp-steps-head {
  width: 100%;
  max-width: var(--exp-w);
  margin: 0 auto;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem;
}
.exp-steps-head .kicker { color: var(--gold); margin-bottom: 0.5rem; }
.exp-steps-head h2 { font-size: clamp(1.5rem, 3.2vw, 2.4rem); }
/* The affordance, said once and quietly: the cards look clickable, this
   only confirms it. Hidden from assistive tech — the buttons announce
   themselves properly. */
.exp-steps-hint {
  font-size: 0.72rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--sand);
  opacity: 0.6;
  white-space: nowrap;
  padding-bottom: 0.4rem;
}

.exp-steps {
  flex: 1;
  min-height: 0;
  width: 100%;
  max-width: var(--exp-w);
  margin: 0 auto;
  display: flex;
  gap: clamp(0.45rem, 0.9vw, 0.9rem);
}
.exp-card {
  position: relative;
  display: flex;                 /* .exp-card__inner is the only in-flow child */
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  border-radius: var(--radius);
  background: #17130f;
  transition: flex-grow 0.65s var(--exp-ease);
}
.exp-card.is-active { flex-grow: var(--exp-open); }

.exp-card__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Shut, the card is taller than the photograph is wide, so cover crops the
     sides and this does nothing. Open, the card is wide and cover takes a
     horizontal band out of the middle — which is how the flame falls out of
     "Tänd elden". Each card names the height its subject actually sits at
     (--exp-focus, set on the <article>); revisit it when a photo changes. */
  object-position: center var(--exp-focus, 50%);
  /* Collapsed cards sit back a step; opening one brings the photograph
     forward and lets a little colour back into it. The step is small on
     purpose: these photographs arrive already dark and lit from one side,
     so the heavy dimming this used to carry (0.68) crushed the stove and
     the sunset to black. The dark ground is in the pictures, not the CSS. */
  filter: saturate(0.92) brightness(0.9);
  transform: scale(1.06);
  transition: filter 0.65s var(--exp-ease), transform 0.9s var(--exp-ease);
}
.exp-card.is-active .exp-card__img { filter: saturate(1.04) brightness(1.06); transform: scale(1); }
.exp-card:not(.is-active):hover .exp-card__img { filter: saturate(1) brightness(1); }

/* Ink behind the type. The ember bloom in the corner is the same warm light
   the hero carries, so an open card reads as lit rather than merely lighter. */
.exp-card__wash {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, rgba(23, 19, 15, 0.9) 0%, rgba(23, 19, 15, 0.55) 28%, rgba(23, 19, 15, 0.06) 62%, rgba(23, 19, 15, 0.22) 100%);
  transition: opacity 0.6s var(--exp-ease);
}
.exp-card.is-active .exp-card__wash {
  background:
    radial-gradient(105% 62% at 8% 112%, rgba(190, 90, 56, 0.34), transparent 62%),
    linear-gradient(to top, rgba(23, 19, 15, 0.9) 0%, rgba(23, 19, 15, 0.6) 38%, rgba(23, 19, 15, 0.08) 78%, rgba(23, 19, 15, 0.2) 100%);
}

.exp-card__inner {
  position: relative;
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  padding: clamp(1.1rem, 1.8vw, 1.9rem);
}
.exp-card__foot { min-width: 0; flex-shrink: 0; }

/* The numeral, over a gold rule that draws itself open. */
.exp-card__num {
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 3vw, 3rem);
  font-weight: 200;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--gold);
  opacity: 0.5;
  margin-bottom: auto;           /* the gap that yields first — see above */
  transition: opacity 0.5s var(--exp-ease);
}
.exp-card__num::before {
  content: "";
  display: block;
  width: 22px;
  height: 2px;
  background: var(--gold);
  margin-bottom: 0.9rem;
  transition: width 0.65s var(--exp-ease);
}
.exp-card.is-active .exp-card__num { opacity: 1; }
.exp-card.is-active .exp-card__num::before { width: 62px; }
.exp-card:not(.is-active):hover .exp-card__num { opacity: 0.8; }

.exp-card__title { margin: 0; }
/* The +/× lives INSIDE the button, not on the <h3>. On the heading it was
   unclickable: a pseudo-element's clicks target its originating element, so
   an "×" drawn by .exp-card__title::after hands the event to the <h3> — a
   parent of the button, which closest(".exp-card__trigger") never matches.
   As the button's own ::after it is simply part of the control. (Small and
   inside the button's box, so it does not hit the Blink clipping described
   further down — that only bites a pseudo-element stretched beyond it.) */
.exp-card__trigger::after {
  content: "+";
  font-size: 1.5rem;
  font-weight: 300;
  line-height: 1;
  color: var(--gold);
  opacity: 0.6;
  flex-shrink: 0;
  transition: opacity 0.3s ease, transform 0.45s var(--exp-ease), font-size 0.65s var(--exp-ease);
}
.exp-card:hover .exp-card__trigger::after { opacity: 1; }
/* Shut, the "+" sits at the far edge of the card, where a list expects it.
   Open, the card is wide and its copy is not, so an edge-anchored "×" would
   float in the middle of a photograph with nothing to belong to — the button
   shrinks to its text so the "×" tucks in beside the heading instead. */
.exp-card.is-active .exp-card__trigger { justify-content: flex-start; width: fit-content; max-width: 100%; }
.exp-card.is-active .exp-card__trigger::after { transform: rotate(45deg); font-size: 1.9rem; }
.exp-card__trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.9rem;
  width: 100%;
  min-width: 0;
  text-align: left;
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.12;
  letter-spacing: -0.015em;
  font-size: clamp(1rem, 1.35vw, 1.25rem);
  color: var(--bone);
  transition: font-size 0.65s var(--exp-ease), transform 0.35s ease;
}
.exp-card.is-active .exp-card__trigger { font-size: clamp(1.55rem, 2.5vw, 2.25rem); }
.exp-card:not(.is-active):hover .exp-card__trigger { transform: translateY(-3px); }
/* A closed card is one big target. This used to be an absolutely positioned
   ::after on the button, stretched over the card — which looks right in
   getComputedStyle and in elementFromPoint, and does not work: Blink clips a
   <button>'s pseudo-element to the button's own box, so every click landed
   on .exp-card__inner instead. The card listens for the click itself now
   (initExpSteps in main.js); this only has to say the card is pressable.
   An open card is deliberately NOT one big target — its heading closes it
   and its CTA has to stay clickable. */
.exp-card:not(.is-active) { cursor: pointer; }
.exp-card__trigger:focus-visible { outline: 2px solid var(--gold); outline-offset: 5px; }

.exp-card__body {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows 0.6s var(--exp-ease), opacity 0.25s ease;
}
.exp-card__body-in { overflow: hidden; min-width: 0; }
.exp-card.is-active .exp-card__body {
  grid-template-rows: 1fr;
  opacity: 1;
  transition: grid-template-rows 0.6s var(--exp-ease), opacity 0.45s ease 0.18s;
}

.exp-card__lead {
  margin-top: 1.1rem;
  font-size: clamp(0.95rem, 1.15vw, 1.08rem);
  line-height: 1.6;
  color: rgba(237, 230, 218, 0.88);
  max-width: 50ch;
}

.exp-card__facts {
  margin-top: 1.4rem;
  display: grid;
  gap: 0.7rem;
  border-top: 1px solid rgba(237, 230, 218, 0.16);
  padding-top: 1rem;
  max-width: 50ch;
}
.exp-card__facts dt {
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--sand);
  opacity: 0.75;
  margin-bottom: 0.15rem;
}
.exp-card__facts dd { font-size: 0.92rem; line-height: 1.45; }
@media (min-width: 560px) {
  .exp-card__facts > div { display: grid; grid-template-columns: 9.5rem 1fr; gap: 1rem; align-items: baseline; }
  .exp-card__facts dt { margin-bottom: 0; }
}
.exp-card__cta { margin-top: 1.6rem; }

/* --- Phone: the row becomes a column, flex-grow moves to height --- */
@media (max-width: 640px) {
  .exp-steps-hint { display: none; }
}
@media (max-width: 899px) {
  .exp-steps { flex-direction: column; gap: 0.5rem; }
  .exp-card { flex: 1 1 auto; min-height: 5.5rem; }
  .exp-card.is-active { flex: 8 1 auto; min-height: 58svh; }
  .exp-card__inner { padding: 1.1rem 1.25rem; gap: 0.75rem; justify-content: flex-start; }
  /* Closed rows read as a list: numeral and title on one line. */
  .exp-card:not(.is-active) .exp-card__inner { flex-direction: row; align-items: center; gap: 1rem; }
  /* A shut row is a wide, shallow crop, so the numeral and title lie across
     the middle of the picture rather than under it — and on the sunset shot
     that middle is the sun's reflection. The scrim turns on its side here:
     heaviest at the left where the type sits, easing right so the
     photograph still shows, but never clearing entirely or the "+" at the
     far edge loses its ground. */
  .exp-card:not(.is-active) .exp-card__wash {
    background: linear-gradient(to right,
      rgba(23, 19, 15, 0.9) 0%, rgba(23, 19, 15, 0.66) 52%, rgba(23, 19, 15, 0.52) 100%);
  }
  .exp-card:not(.is-active) .exp-card__foot { flex: 1; }
  .exp-card:not(.is-active) .exp-card__num { font-size: 1.35rem; opacity: 0.85; margin-bottom: 0; }
  .exp-card:not(.is-active) .exp-card__num::before { display: none; }
  .exp-card:not(.is-active) .exp-card__trigger { font-size: 1.05rem; }
  .exp-card.is-active .exp-card__num { margin-bottom: 0.2rem; }
  .exp-card__lead { margin-top: 0.8rem; }
  .exp-card__body-in { padding-bottom: 0.4rem; }
}
@media (min-width: 900px) {
  /* Fixed so the copy keeps its measure while the card is still narrow —
     the card clips it, rather than re-wrapping it to a 200px column. */
  .exp-card__body-in { width: min(54ch, 40vw); }
}

@media (prefers-reduced-motion: reduce) {
  .exp-card,
  .exp-card__img,
  .exp-card__num,
  .exp-card__num::before,
  .exp-card__trigger::after,
  .exp-card__trigger,
  .exp-card__body { transition-duration: 0.01ms; }
}

/* ============ Member area (mina-sidor.html) ============
   The other register of the site: the same brand, turned down and inward.
   Everything account-shaped links out to Mana. */
.member-mode { background: var(--ember-black); color: var(--bone); }
.member-mode a { color: var(--bone); }
.member-mode .kicker { color: var(--sand); }
.member-mode .card { background: rgba(237, 230, 218, 0.06); }
.member-mode .mana-card {
  background: rgba(237, 230, 218, 0.06);
  border: 1px solid rgba(237, 230, 218, 0.12);
}
.member-mode .mana-meta { color: var(--gold); }
.member-mode .mana-actions .btn-quiet { color: var(--bone); }
.member-mode .btn-outline { border-color: rgba(237, 230, 218, 0.5); color: var(--bone); }
.member-mode .btn-outline:hover { background: var(--bone); color: var(--ember-black); }
/* The trial band is already dark; on this page it needs the opposite edge */
.member-mode .mana-trial { border: 1px solid rgba(237, 230, 218, 0.16); }

/* The temperature band is already ember black, so on this page it would
   vanish into the background — it borrows a hairline and a lift instead. */
.member-mode .temp-band {
  background: rgba(237, 230, 218, 0.05);
  border-bottom: 1px solid rgba(237, 230, 218, 0.12);
}

.member-hero { padding: clamp(3rem, 8vw, 5.5rem) 0 clamp(2rem, 5vw, 3rem); }
.member-hero h1 { font-size: clamp(2.4rem, 6vw, 3.8rem); margin-bottom: 1.2rem; }
.member-hero .feature-cta { margin-top: 2rem; }
.member-note { font-size: 0.82rem; opacity: 0.55; margin-top: 1.4rem; }
.member-prelaunch { margin-top: 1.6rem; opacity: 0.75; max-width: 52ch; }
.member-sub { margin: 0.8rem 0 0; }

/* Signpost tiles — each one a door into Mana, none of it rebuilt here. */
.member-tiles {
  display: grid;
  gap: 0.9rem;
  margin-top: 2.2rem;
}
@media (min-width: 640px) { .member-tiles { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 960px) { .member-tiles { grid-template-columns: repeat(3, 1fr); } }
.member-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 1.5rem 3rem 1.5rem 1.5rem;
  border: 1px solid rgba(237, 230, 218, 0.16);
  border-radius: var(--radius);
  text-decoration: none;
  transition: border-color 0.2s ease, background 0.2s ease;
}
.member-tile:hover { border-color: var(--gold); background: rgba(237, 230, 218, 0.05); }
.member-tile-title { font-family: var(--font-display); font-size: 1.1rem; }
.member-tile-body { font-size: 0.9rem; opacity: 0.65; }
.member-tile-arrow {
  position: absolute;
  right: 1.4rem;
  top: 1.5rem;
  opacity: 0.4;
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.member-tile:hover .member-tile-arrow { opacity: 1; transform: translateX(3px); }

.member-join {
  border-top: 1px solid rgba(237, 230, 218, 0.16);
  padding-top: 2.5rem;
}
.member-join p { margin-top: 0.6rem; opacity: 0.7; }
.member-join .feature-cta { margin-top: 1.6rem; }
.member-mode .feature-cta .btn-quiet { color: var(--bone); }

/* Dark CTA band — the last thing the home page says, and the closing ask on
   the FAQ and journal pages. */
.cta-band { text-align: center; }
.cta-band h2 { max-width: 20ch; margin: 0 auto 1.2rem; }
.cta-band .lede { max-width: 54ch; margin: 0 auto; }
.cta-band .feature-cta { margin-top: 2rem; }
/* A dark closing band sits directly above a dark footer, so without an edge
   the two merge into one slab with 190px of nothing between the button and
   the footer logo. A hairline and a shorter foot make them two things. */
main > .cta-band.dark:last-child,
main > .contact-close.dark:last-child {
  padding-bottom: clamp(2.75rem, 6vw, 4.25rem);
  border-bottom: 1px solid rgba(237, 230, 218, 0.12);
}

/* The second paragraph of "why we started" — set under the two-column head,
   at a reading measure rather than across the full band. */

/* Contact block */
/* (A stray `.cta-band` was left dangling above this selector, which made the
   whole rule `.cta-band .contact-grid` — so the contact block on the FAQ and
   places pages was never a grid at all, and its three-column media query had
   nothing to apply to.) */
.contact-grid { display: grid; gap: 1.5rem; }
@media (min-width: 700px) { .contact-grid { grid-template-columns: repeat(3, 1fr); } }
.contact-grid h3 { font-size: 0.82rem; font-family: var(--font-body); font-weight: 500; letter-spacing: 0.22em; text-transform: uppercase; opacity: 0.6; margin-bottom: 0.4rem; }

/* Contact cards — the FAQ page's close. The old block set the label, the
   value and the action as three separate lines of text, so the only thing
   you could actually click was a five-word link; here the whole card is the
   target. Laid out as one slab divided by hairlines rather than three
   floating boxes: the seam is the 1px grid gap showing through. */
.contact-close .lede { margin-top: 1rem; max-width: 48ch; }
.contact-cards {
  display: grid;
  gap: 1px;
  margin-top: clamp(2rem, 4vw, 2.9rem);
  background: rgba(237, 230, 218, 0.16);   /* shows through the gaps */
  border: 1px solid rgba(237, 230, 218, 0.16);
}
@media (min-width: 760px) { .contact-cards { grid-template-columns: repeat(3, 1fr); } }
.contact-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
  padding: clamp(1.5rem, 3.2vw, 2rem);
  background: var(--ember-black);
  text-decoration: none;
  transition: background 0.25s ease;
}
.contact-card:hover, .contact-card:focus-visible { background: #2b241e; }
.contact-card:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
.contact-icon {
  width: 26px; height: 26px;
  stroke: var(--gold);
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--gold);          /* the Instagram lens dot fills off this */
  margin-bottom: 0.7rem;
  transition: transform 0.25s ease;
}
.contact-card:hover .contact-icon { transform: translateY(-2px); }
.contact-card h3 {
  font-family: var(--font-body);
  font-size: 0.74rem;
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--sand);
}
/* The address is the longest value and the email has no spaces to break on,
   so both are told they may break mid-word rather than widen the column. */
.contact-val { font-size: 1.02rem; line-height: 1.5; overflow-wrap: anywhere; }
.contact-go {
  margin-top: auto;
  padding-top: 0.9rem;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--gold);
}
.contact-go::after { content: " →"; display: inline-block; transition: transform 0.25s ease; }
.contact-card:hover .contact-go::after { transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) {
  .contact-icon, .contact-go::after { transition: none; }
  .contact-card:hover .contact-icon, .contact-card:hover .contact-go::after { transform: none; }
}

/* ============ Legal documents (terms, privacy) ============ */
.legal-doc { max-width: 68ch; }
.legal-doc h2 {
  font-size: clamp(1.15rem, 2.2vw, 1.4rem);
  margin-top: 2.6rem;
  letter-spacing: -0.005em;
}
.legal-doc h2 + p { margin-top: 0.7rem; }
.legal-updated {
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  opacity: 0.55;
  margin-bottom: 1.4rem;
}
.legal-contact { margin-top: 2.8rem; font-weight: 500; }
.legal-disclaimer {
  margin-top: 1.6rem;
  padding: 1rem 1.2rem;
  border-left: 2px solid var(--ember);
  background: rgba(190, 90, 56, 0.06);
  font-size: 0.88rem;
  opacity: 0.8;
}

/* ============ Journal ============ */
.journal-empty {
  margin-top: 2.4rem;
  padding: 2.2rem 0 0;
  border-top: 1px solid rgba(32, 27, 23, 0.12);
  max-width: 52ch;
}
.journal-empty p { opacity: 0.75; }

/* Entry list — unused until the first post ships, kept so adding one is
   markup only (see the pattern commented in journal.html). */
.journal-list { list-style: none; margin-top: 2.4rem; display: grid; gap: 0; }
.journal-entry { border-top: 1px solid rgba(32, 27, 23, 0.12); }
.journal-entry:last-child { border-bottom: 1px solid rgba(32, 27, 23, 0.12); }
.journal-entry a {
  display: block;
  padding: 1.8rem 0;
  text-decoration: none;
  transition: opacity 0.15s ease;
}
.journal-entry a:hover { opacity: 0.7; }
.journal-date {
  display: block;
  font-size: 0.75rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  opacity: 0.5;
  margin-bottom: 0.5rem;
}
.journal-entry h3 { margin-bottom: 0.4rem; }
.journal-entry p { opacity: 0.75; max-width: 60ch; }

/* ============ Footer ============ */
#site-footer {
  background: var(--ember-black);
  color: var(--bone);
  margin-top: auto;
}
.footer-inner {
  max-width: var(--max-w);
  margin: 0 auto;
  padding: clamp(3rem, 7vw, 5rem) var(--pad) 2.5rem;
  display: grid;
  gap: 2.5rem;
}
/* brand block wider than the three link columns, as in the reference */
@media (min-width: 620px) and (max-width: 979px) {
  .footer-inner { grid-template-columns: 1fr 1fr; gap: 2.6rem 3rem; }
}
@media (min-width: 980px) {
  .footer-inner { grid-template-columns: 1.7fr 1fr 1fr 1.1fr; gap: 3.5rem; }
}
.footer-brand p {
  margin: 1.1rem 0 1.6rem;
  opacity: 0.7;
  font-size: 0.92rem;
  line-height: 1.6;
  max-width: 30ch;
}
.footer-social { display: flex; gap: 0.9rem; }
.footer-social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: 1px solid rgba(237, 230, 218, 0.28);
  border-radius: 2px;
  opacity: 0.8;
  transition: opacity 0.15s ease, border-color 0.15s ease;
}
.footer-social a:hover { opacity: 1; border-color: var(--sand); }
/* the CTA column sits on the same baseline as the link lists, and the button
   carries the same uppercase treatment as the header and hero CTAs */
.footer-col-join .btn {
  align-self: flex-start;
  margin-top: 0.2rem;
  text-transform: uppercase;
  letter-spacing: 0.17em;
  font-size: 0.68rem;
  font-weight: 600;
  padding: 0.85rem 1.5rem;
}
.footer-col { display: flex; flex-direction: column; gap: 0.55rem; font-size: 0.9rem; }
.footer-head {
  font-size: 0.75rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  opacity: 0.5;
  margin-bottom: 0.3rem;
  font-weight: 600;
}
.footer-col a { text-decoration: none; opacity: 0.8; }
.footer-col a:hover { opacity: 1; color: var(--sand); }
.footer-col span { opacity: 0.65; }
.footer-legal {
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 1.4rem var(--pad) 2.2rem;
  border-top: 1px solid rgba(237, 230, 218, 0.1);
  font-size: 0.78rem;
  opacity: 0.45;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.5rem;
  justify-content: space-between;
}

/* Page shell so the footer hugs the bottom */
body { display: flex; flex-direction: column; min-height: 100vh; }
main { flex: 1; }
