/*
 * app.css — the page itself: the site chrome, and the layouts the screens use.
 *
 * Everything here is composition. The components and their constraints are in
 * components.css; the values are in tokens.css. No raw colour, size, radius or
 * spacing number appears below.
 */

/* ─────────────────────────── modera.studio chrome ───────────────────────────
 *
 * The bar at the top is the site's, not the app's: Cormorant wordmark, a
 * hairline rule, quiet links. It is what makes this read as a page of
 * modera.studio rather than as an app screenshot on a white background.
 *
 * It is also outside the accent budget, exactly as the app's tab bar is. The
 * bar is on every screen, so read literally the one-accent rule would forbid
 * an accent anywhere in it or forbid a primary action on every screen that has
 * it — and both readings are wrong. What the rule protects is that two things
 * on a screen must never compete for "most important", and persistent chrome
 * does not compete; the eye reads it as the constant the content sits inside.
 * There is no accent in this bar either way.
 */
.site-nav {
  position: sticky;
  top: 0;
  z-index: 40;
  padding: 12px 0;
  backdrop-filter: saturate(1.4) blur(14px);
  -webkit-backdrop-filter: saturate(1.4) blur(14px);
  background: color-mix(in srgb, var(--base) 86%, transparent);
  border-bottom: 1px solid var(--site-rule-soft);
}
/*
 * The site's own grid: brand left, links optically centred, one pill right.
 * The outer columns are `1fr` so the links sit on the page's centre line
 * rather than on the midpoint between two unequal neighbours.
 */
.site-nav-inner {
  max-width: var(--site-max);
  margin-inline: auto;
  /* The site's own container gutter, so the wordmark lands on the same
     vertical as the one on the page you just came from. */
  padding-inline: clamp(20px, 4vw, 56px);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 24px;
}
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  white-space: nowrap;
}
.wordmark img {
  height: 28px;
  width: auto;
  filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.05));
}
.wordmark span {
  font-family: var(--display-face);
  font-weight: 500;
  font-size: 22px;
  letter-spacing: 0.02em;
  color: var(--text);
}
#nav-links {
  display: flex;
  align-items: center;
  gap: clamp(20px, 2.4vw, 36px);
  justify-self: center;
}
#nav-links a {
  position: relative;
  white-space: nowrap;
  font-family: var(--body);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
  padding: 6px 2px;
  transition: color var(--motion-tap);
}
#nav-links a:hover { color: var(--text); }
#nav-links a[aria-current='page'] { color: var(--text); }
/*
 * The site marks the current page with a short accent dash, not a full-width
 * rule. It is the one place the accent appears in the bar, and it is the
 * site's mark rather than the app's — see the note above on chrome sitting
 * outside the accent budget.
 */
#nav-links a[aria-current='page']::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -2px;
  width: 14px;
  height: 1px;
  background: var(--site-accent);
  transform: translateX(-50%);
}
.site-nav-cta {
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
  font-family: var(--body);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text);
  border: 1px solid var(--text);
  padding: 10px 18px;
  border-radius: 999px;
  transition: background var(--motion-tap), color var(--motion-tap);
}
.site-nav-cta:hover { background: var(--text); color: var(--base); }

/* ─────────────────────────────── screens ─────────────────────────────── */

/*
 * The bar's height, named because two surfaces below size themselves against
 * the space it leaves. The value here is only the first paint's guess —
 * `app.js` measures the real bar and writes it back, because the bar is taller
 * on a narrow window and a stale number crops the room by the difference.
 */
:root { --nav-height: 57px; }

#main { min-height: calc(100dvh - var(--nav-height)); display: flex; flex-direction: column; }

.page {
  width: 100%;
  max-width: var(--site-max);
  margin-inline: auto;
  padding: var(--space-xl) 0 var(--space-xxxl);
  display: flex;
  flex-direction: column;
  gap: var(--section-gap);
}

/*
 * The create sequence and the room share one shape: the render filling the
 * surface, chrome floating over it. The room is the content and the interface
 * is a thin layer of light on top, which is the whole reason the panel is
 * anchored to the bottom rather than beside it.
 */
/*
 * A DEFINITE HEIGHT, AND THE CANVAS TAKEN OUT OF THE FLOW. Both of these are
 * load-bearing and the reason is the same feedback loop.
 *
 * `resize()` sets the drawing buffer from the stage's client height. A canvas
 * sized `height: 100%` inside an auto-height parent resolves to auto, which
 * for a canvas means its own buffer height — so the parent takes its height
 * from the canvas, the canvas takes its buffer from the parent, and each
 * ResizeObserver tick makes both a little bigger. On the room screen, whose
 * side panel is tall enough to push the row past the viewport, this ran away
 * to a canvas twenty-one thousand pixels tall before anything visibly broke.
 *
 * So the surface is sized against the viewport rather than its content, and
 * the canvas is positioned out of the flow so it cannot contribute a height
 * back. Either one alone stops the runaway; both is the honest fix.
 */
.flow, .room-screen {
  position: relative;
  flex: 1 1 auto;
  height: calc(100dvh - var(--nav-height));
  min-height: 0;
  display: grid;
  grid-template-rows: 1fr;
}
.flow-stage { position: relative; grid-area: 1 / 1; overflow: hidden; }
.flow-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }

.flow-header {
  grid-area: 1 / 1;
  align-self: start;
  justify-self: stretch;
  padding-top: var(--space-sm);
  pointer-events: none;
}
.flow-header-row { display: flex; align-items: center; gap: var(--space-sm); }
.flow-header-row > * { pointer-events: auto; }
.flow-header-spacer { flex: 1 1 0; min-width: 40px; }

.flow-panel {
  grid-area: 1 / 1;
  align-self: end;
  justify-self: stretch;
  padding-bottom: var(--space-md);
  /* The panel scrolls when a step has a lot in it — the openings step with an
   * opening selected is the tall one — rather than pushing the room off. */
  max-height: min(78%, 720px);
  overflow-y: auto;
  scrollbar-width: none;
}
.flow-panel::-webkit-scrollbar { display: none; }

/* ─────────────────────────── the preset picker ─────────────────────────── */

.preset-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: var(--grid-gutter);
}
.preset { display: flex; flex-direction: column; gap: var(--text-gap); text-align: left; }
.preset figure {
  aspect-ratio: 1;
  border-radius: var(--radius-thumbnail);
  overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--edge);
  transition: box-shadow var(--motion-tap);
}
.preset[aria-pressed='true'] figure { box-shadow: inset 0 0 0 2px var(--text); }
.preset .ds-body-lg { font: var(--type-body); }

/* ──────────────────────────── the chooser ──────────────────────────── */

.filmstrip { display: flex; gap: var(--grid-gutter); }
.filmstrip-option { flex: 1 1 0; }
.filmstrip-option figure {
  aspect-ratio: var(--ratio-scene);
  border-radius: var(--radius-thumbnail);
  overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--edge);
  transition: box-shadow var(--motion-tap), transform var(--motion-tap);
}
.filmstrip-option[aria-pressed='true'] figure {
  box-shadow: inset 0 0 0 2px var(--text);
  transform: translateY(-2px);
}

/* The wait's bar. One continuous run, because this is the warm surface: the
 * app segments it only for the cold minute, and there is no cold minute here. */
.wait-bar {
  height: var(--space-xxs);
  border-radius: var(--radius-control);
  background: var(--surface-sunken);
  overflow: hidden;
}
.wait-bar i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--text);
  border-radius: inherit;
  transition: width var(--motion-transition);
}

/* ──────────────────────────── the room ──────────────────────────── */

.room-screen { grid-template-columns: 1fr; }
.room-overlay { grid-area: 1 / 1; align-self: start; padding-top: var(--space-sm); pointer-events: none; }
.room-overlay-row { display: flex; align-items: center; gap: var(--space-sm); flex-wrap: wrap; }
.room-overlay-row > *, .room-overlay-row .ds-chip { pointer-events: auto; }

.room-panel {
  grid-area: 1 / 1;
  align-self: end;
  position: relative;
  width: min(100%, var(--panel-column));
  margin-inline: auto;
  margin-bottom: var(--space-md);
  padding: var(--space-lg);
  max-height: 72%;
  overflow-y: auto;
  scrollbar-width: none;
  background: var(--glass-fill);
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  border-radius: var(--radius-sheet);
  box-shadow: var(--elevation-floating-modern), var(--glass-inner);
  isolation: isolate;
}
/* The rim is a sticky pseudo-element rather than ::after on the scroller,
 * because a scrolling panel would otherwise carry its own edge up out of view. */
.room-panel::after {
  content: '';
  position: sticky;
  display: block;
  bottom: 0;
  height: 0;
  box-shadow: 0 0 0 100vmax transparent;
  pointer-events: none;
}
.room-panel::-webkit-scrollbar { display: none; }

.product-row {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-xs);
  border-radius: var(--radius-thumbnail);
  transition: background var(--motion-tap);
}
.product-row:hover { background: color-mix(in srgb, var(--text) 5%, transparent); }
.product-row figure { width: 44px; height: 44px; flex: 0 0 auto; overflow: hidden; }

.alternate-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  gap: var(--grid-gutter);
}
.alternate { display: flex; flex-direction: column; gap: 2px; text-align: left; }
.alternate figure {
  aspect-ratio: 1;
  border-radius: var(--radius-thumbnail);
  overflow: hidden;
  transition: box-shadow var(--motion-tap);
}
.alternate:hover figure { box-shadow: inset 0 0 0 2px var(--text); }

.placeholder { padding: var(--space-sm); display: flex; flex-direction: column; gap: var(--text-gap); }

/* ─────────────────────────── cards and grids ─────────────────────────── */

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: var(--space-lg) var(--grid-gutter);
}
.plan-figure { width: 100%; height: 100%; background: var(--surface); }
.plan-figure svg { width: 100%; height: 100%; }
.card-remove { color: var(--text-secondary); align-self: flex-start; padding-top: var(--space-xxs); }
.card-remove:hover { color: var(--text); }

.chip-row { display: flex; gap: var(--space-xs); overflow-x: auto; scrollbar-width: none; }
.chip-row::-webkit-scrollbar { display: none; }
.chip-row--wrap { flex-wrap: wrap; overflow: visible; }
.button-row { display: flex; gap: var(--space-xs); }

/* ─────────────────────────────── wide ───────────────────────────────
 *
 * DS.Breakpoint.wide is 700 and is the one layout breakpoint. Past it the
 * panel stops floating over the room and stands beside it: on a laptop a
 * bottom sheet covering the lower third of a 3D room is a phone habit, and the
 * room is the subject.
 */
@media (min-width: 700px) {
  .flow { grid-template-columns: 1fr minmax(360px, 30%); }
  .flow-stage { grid-area: 1 / 1 / 2 / 2; border-radius: var(--radius-scene); margin: var(--content-margin); }
  .flow-header { grid-area: 1 / 1 / 2 / 2; padding-inline: var(--space-xl); }
  .flow-panel {
    grid-area: 1 / 2 / 2 / 3;
    align-self: center;
    max-height: none;
    padding-inline: var(--space-md) var(--content-margin);
  }
  .flow-panel .step-panel { width: 100%; }

  .room-screen { grid-template-columns: 1fr minmax(360px, 32%); }
  .room-screen .flow-stage { grid-area: 1 / 1 / 2 / 2; border-radius: var(--radius-scene); margin: var(--content-margin); }
  .room-overlay { grid-area: 1 / 1 / 2 / 2; padding-inline: var(--space-xl); }
  .room-panel {
    grid-area: 1 / 2 / 2 / 3;
    align-self: center;
    /* `width: min(100%, …)` plus margins overflowed its own column by the
       width of both margins, and the last line of copy ran off the window. */
    width: auto;
    margin-block: var(--content-margin);
    margin-inline: var(--space-md) var(--content-margin);
    max-height: calc(100dvh - var(--nav-height) - var(--space-xxl));
  }
}

/*
 * Narrow. The bar has to stay one line: it is the thing every surface below
 * measures itself against, and a bar that wraps changes height mid-flow and
 * crops the room.
 */
@media (max-width: 860px) {
  /* The pill is the first thing to go: the route links are how the app works,
     and the waitlist is one tap away on the site the wordmark returns to. */
  .site-nav-cta { display: none; }
  .site-nav-inner { grid-template-columns: auto 1fr; }
  #nav-links { justify-self: end; gap: 18px; }
}
@media (max-width: 480px) {
  .site-nav-inner { gap: var(--space-sm); padding-inline: var(--content-margin); }
  .wordmark span { display: none; }
  .wordmark img { height: 24px; }
  #nav-links { gap: var(--space-sm); }
  #nav-links a { font-size: 11px; letter-spacing: 0.04em; }
}
