/* ── Shell ─────────────────────────────────────────────────────────
   The app is a sidebar plus a column. `body` is the flex row (base.css sets
   min-height:100svh and display:flex); `.app-main` is the column inside it,
   and `main { flex: 1 }` inside that column is what puts the footer on the
   bottom edge of the viewport instead of under the last element.

   Nothing here is positioned fixed except the sidebar and its backdrop while
   it is off-canvas. */

body.has-sidebar { flex-direction: row; }

.app-main {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;                 /* without this a wide table stretches the row */
  min-height: 100svh;
}

.shell {
  max-width: var(--shell);
  margin: 0 auto;
  width: 100%;
  padding: 0 14px;
}
@media (min-width: 700px) { .shell { padding: 0 20px; } }

/* ── App bar ───────────────────────────────────────────────────────
   Exists to carry the sidebar toggle and the wordmark on a narrow screen,
   and to keep the anonymous pages from looking like a broken host. From
   960px the toggle is gone, so on authenticated pages the bar collapses to
   just the wordmark — which the sidebar already shows, so it is hidden. */

.app-bar {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: 10px;
  padding: 6px 12px;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line-soft);
}
@media (min-width: 700px) { .app-bar { padding: 8px 20px; } }
@media (min-width: 960px) { body.has-sidebar .app-bar { display: none; } }

.sb-toggle {
  flex: none;
  width: var(--tap); height: var(--tap);
  display: grid; place-items: center;
  background: none; border: 1px solid var(--line);
  border-radius: var(--brick-sm);
  color: var(--ink); cursor: pointer;
  transition: background .2s, border-radius .25s;
}
.sb-toggle:hover { background: var(--surface-2); border-radius: var(--brick-sm-flip); }
.sb-toggle i {
  display: block; width: 17px; height: 2px; background: currentColor;
  border-radius: 2px; position: relative;
}
.sb-toggle i::before, .sb-toggle i::after {
  content: ''; position: absolute; left: 0; width: 17px; height: 2px;
  background: currentColor; border-radius: 2px;
}
.sb-toggle i::before { top: -5px; }
.sb-toggle i::after { top: 5px; }

.brand {
  font-family: var(--font-display); font-weight: 900; font-size: 1.02rem;
  letter-spacing: -0.02em; text-decoration: none; color: var(--ink);
  display: inline-flex; align-items: center; gap: 8px;
  min-height: var(--tap);
}

/* The backdrop only exists while the sidebar is open off-canvas. Clicking it
   closes the sidebar; shell.js owns that. */
.sb-backdrop {
  position: fixed; inset: 0; z-index: 55;
  background: rgba(34, 34, 42, .42);
  border: 0; padding: 0; cursor: pointer;
}
@media (min-width: 960px) { .sb-backdrop { display: none; } }

/* Keyboard users get out of the sidebar in one key. */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--slate); color: #fff; padding: 10px 14px;
  border-radius: 0 0 var(--brick-sm);
  font-size: 13px; font-weight: 700; text-decoration: none;
}
.skip-link:focus { left: 0; }

/* flex:1 lets main absorb the leftover height from the column, which is what
   actually holds the footer down. The bottom padding clears the coach
   launcher and the phone's gesture bar. */
main { flex: 1; padding: 18px 0 calc(80px + env(safe-area-inset-bottom)); }
@media (min-width: 700px) { main { padding: 26px 0 76px; } }

/* Anonymous pages have no sidebar: centre the content column. */
main.anon-main { display: flex; flex-direction: column; justify-content: center; }

/* ── Footer ────────────────────────────────────────────────────────
   Small on purpose. This is a personal platform, not a marketing site. It
   sits on the bottom edge because main above it grows, not because it is
   pinned there. */

.app-foot {
  border-top: 1px solid var(--line-soft);
  padding: 16px 0 calc(20px + env(safe-area-inset-bottom));
  color: var(--muted); font-size: 12.5px;
}
.app-foot-inner { display: flex; flex-direction: column; gap: 4px; }
@media (min-width: 700px) {
  .app-foot-inner { flex-direction: row; align-items: center; gap: 14px; }
  .app-foot-link { margin-left: auto; }
}
.app-foot-brand { font-family: var(--font-display); font-weight: 900; color: var(--ink); }
.app-foot-link { color: var(--blue-deep); min-height: 32px; display: inline-flex; align-items: center; }

/* ── Bento grid ────────────────────────────────────────────────────
   One column on a phone. Two from 560px. Six from 900px, where the
   asymmetric spans finally mean something. */

.bento { display: grid; grid-template-columns: 1fr; gap: var(--gap); }
.bento > * { min-width: 0; }

@media (min-width: 560px) {
  .bento { grid-template-columns: repeat(2, 1fr); }
  .span-2, .span-3, .span-4, .span-6 { grid-column: span 2; }
  .span-1-sm { grid-column: span 1; }
}
@media (min-width: 900px) {
  .bento { grid-template-columns: repeat(6, 1fr); }
  .span-2 { grid-column: span 2; }
  .span-3 { grid-column: span 3; }
  .span-4 { grid-column: span 4; }
  .span-6 { grid-column: span 6; }
}
