/* dommicheli.com - core stylesheet
   No build step, no dependencies. Keep everything in this file.
   The CSP has no 'unsafe-inline', so there are no <style> blocks or style=""
   attributes anywhere in the site. Every rule lives here. */

:root {
  --bg:         #05080f;
  --bg-panel:   #0a1018;
  --bg-raise:   #101823;
  --line:       #18222f;
  --line-soft:  #111925;
  --text:       #c2ccd9;
  --text-hi:    #e9f0f8;
  --muted:      #64717f;

  --accent:     #40d6a8;   /* foreground green */
  --accent-dim: #1d6b55;
  --accent-ghost: rgba(64, 214, 168, 0.08);
  --blue:       #4aa8f0;   /* horizon blue */
  --blue-dim:   #235f96;
  --warn:       #e0a145;

  --mono: "JetBrains Mono", "Cascadia Code", ui-monospace, SFMono-Regular,
          "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

  --gap: clamp(1.25rem, 4vw, 2.5rem);
  --maxw: 64rem;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--mono);
  font-size: clamp(0.875rem, 0.8rem + 0.25vw, 0.95rem);
  line-height: 1.65;
  font-variant-ligatures: none;
  display: flex;
  flex-direction: column;
}

/* Faint engineering grid on the interior pages. The home page has the ocean
   canvas instead, so it opts out. */
body:not(.home)::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(60rem 40rem at 50% -10%, rgba(64, 214, 168, 0.06), transparent 70%),
    linear-gradient(var(--line-soft) 1px, transparent 1px) 0 0 / 100% 2.5rem,
    linear-gradient(90deg, var(--line-soft) 1px, transparent 1px) 0 0 / 2.5rem 100%;
  mask-image: radial-gradient(75rem 60rem at 50% 20%, #000 30%, transparent 80%);
}

/* ==========================================================================
   HOME PAGE
   ========================================================================== */

body.home {
  display: block;
  overflow: hidden;
  /* Fallback only: the whole show if JavaScript is off. These are big static colour
     washes, and once the canvas is painting they sit behind the grid as lineless
     haze that never moves - so ocean.js marks the document and they come straight
     back off. */
  background:
    radial-gradient(120% 80% at 50% 108%, rgba(64, 214, 168, 0.16), transparent 60%),
    radial-gradient(90% 60% at 50% 30%, rgba(35, 95, 150, 0.20), transparent 70%),
    linear-gradient(180deg, #04070d 0%, #05080f 45%, #061019 100%);
}

/* Canvas is live: plain night sky, faintly lifted where the horizon sits. Every
   other bit of light on this page is now drawn, not painted on behind it. */
.ocean-live body.home {
  background: linear-gradient(180deg,
    #03060c 0%,
    #04080f 22%,
    #061220 37%,
    #040a12 62%,
    #03070d 100%);
}

.ocean {
  position: fixed;
  inset: 0;
  z-index: 0;
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0;
}
.ocean.live { animation: ocean-in 2.2s 0.15s ease-out forwards; }

@keyframes ocean-in { to { opacity: 1; } }

/* Feather the left and right edges only - the old radial mask also faded the top of
   the frame, which would have dimmed the moon and the cloud banks out of existence,
   and the water needs no vertical fade since the far rows already dim toward the
   horizon through their own alpha.

   This used to be a mask-image on the canvas itself. Masking content that repaints
   every frame is expensive in WebKit - the browser has to recomposite the mask
   against the canvas's new pixels 60 times a second instead of caching it as a
   static layer, and that was a real source of the stutter this page used to have.
   These two static strips paint the same background gradient the page already
   sits on and fade it out toward the centre, sitting above the (now unmasked,
   full-bleed) canvas - same look, no per-frame masking. */
.ocean-edge {
  position: fixed;
  top: 0;
  bottom: 0;
  z-index: 0;
  width: 9vw;
  pointer-events: none;
  background: linear-gradient(180deg,
    #03060c 0%, #04080f 22%, #061220 37%, #040a12 62%, #03070d 100%);
  opacity: 0;
  transition: opacity 1.2s ease-out;
}
.ocean-live .ocean-edge { opacity: 1; }
.ocean-edge.left {
  left: 0;
  mask-image: linear-gradient(90deg, #000 0%, transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, #000 0%, transparent 100%);
}
.ocean-edge.right {
  right: 0;
  mask-image: linear-gradient(270deg, #000 0%, transparent 100%);
  -webkit-mask-image: linear-gradient(270deg, #000 0%, transparent 100%);
}

.home-shell {
  position: relative;
  z-index: 1;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 2rem var(--gap);
}

.home-main {
  position: relative;
  text-align: center;
  max-width: 42rem;
}

/* No panel behind the copy. Legibility is carried by the glyphs themselves - see the
   halo on .wordmark and .tagline below. Any shaped scrim, however soft, has an edge
   you can eventually see; a halo that hugs the letterforms has none, and the grid
   runs unbroken behind the type. */

.wordmark {
  margin: 0;
  font-size: clamp(1.75rem, 0.95rem + 5.3vw, 4.25rem);
  line-height: 1.03;
  letter-spacing: -0.045em;
  font-weight: 600;
  color: var(--text-hi);
  /* Three stacked shadows: a dense core to guarantee contrast against a bright wave
     crest, then two wide soft passes so the falloff reads as atmosphere. */
  filter:
    drop-shadow(0 0 10px rgba(3, 6, 12, 0.95))
    drop-shadow(0 0 30px rgba(3, 6, 12, 0.8))
    drop-shadow(0 0 64px rgba(3, 6, 12, 0.55));
  animation: rise 0.9s 0.25s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .wordmark {
    background: linear-gradient(103deg,
      #40d6a8 0%, #85ecd2 26%, #9fd9f4 58%, #4aa8f0 88%, #3d8fd8 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
  }
}

.tagline {
  margin: 1.5rem 0 0;
  color: var(--muted);
  font-size: clamp(0.6875rem, 0.65rem + 0.22vw, 0.8125rem);
  letter-spacing: 0.24em;
  color: #8492a2;   /* lifted a step, since there is no longer a scrim behind it */
  text-shadow:
    0 0 8px rgba(3, 6, 12, 0.98),
    0 0 20px rgba(3, 6, 12, 0.9),
    0 0 44px rgba(3, 6, 12, 0.7);
  animation: rise 0.9s 0.42s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.enter {
  display: inline-block;
  margin-top: 3rem;
  padding: 0.8rem 3.75rem;
  border: 1px solid rgba(64, 214, 168, 0.28);
  border-radius: 999px;
  background: rgba(5, 13, 20, 0.62);
  box-shadow: 0 0 30px 10px rgba(3, 6, 12, 0.45);
  color: var(--accent);
  text-decoration: none;
  font-size: 0.8125rem;
  letter-spacing: 0.2em;
  text-indent: 0.2em;   /* offset the trailing letter-space so the word sits centred */
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: border-color 0.25s ease, background 0.25s ease,
              transform 0.25s ease, box-shadow 0.25s ease;
  animation: rise 0.9s 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.enter:hover, .enter:focus-visible {
  border-color: rgba(74, 168, 240, 0.6);
  background: rgba(10, 28, 40, 0.72);
  transform: translateY(-2px);
  box-shadow:
    0 0 30px 10px rgba(3, 6, 12, 0.45),
    0 0.75rem 2rem -0.9rem rgba(64, 214, 168, 0.65);
}

@keyframes rise {
  from { opacity: 0; transform: translateY(1.1rem); }
  to   { opacity: 1; transform: none; }
}

/* ==========================================================================
   INTERIOR PAGES
   ========================================================================== */

.shell {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--gap);
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}

.topbar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1.25rem 0;
  border-bottom: 1px solid var(--line);
  font-size: 0.8125rem;
}

.topbar .host { color: var(--text-hi); letter-spacing: 0.02em; text-decoration: none; }
.topbar .host:hover { color: var(--accent); }
.topbar .sep  { color: var(--line); }
.topbar .meta { color: var(--muted); }
.topbar nav   { margin-left: auto; display: flex; align-items: center; gap: 1.25rem; }

.dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0.5rem var(--accent);
  flex: none;
  animation: pulse 3.2s ease-in-out infinite;
}

@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

main { padding: clamp(2.5rem, 7vh, 4.5rem) 0 clamp(3rem, 9vh, 6rem); }

.site-footer {
  position: relative;
  z-index: 1;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.75rem;
}
.site-footer .inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 1.25rem var(--gap);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1.5rem;
}
.site-footer .spacer { margin-left: auto; }
.site-footer .ok { color: var(--accent); }

/* ---------- section scaffolding ---------- */

.section { margin-top: clamp(3rem, 8vh, 5rem); }

.section-head {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.75rem;
}
.section-head h2 {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}
.section-head .idx { color: var(--accent-dim); }
.section-head::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

.rule { height: 1px; background: var(--line); margin: 2.5rem 0; border: 0; }

/* ---------- hero ---------- */

.hero h1 {
  margin: 0;
  font-size: clamp(2rem, 1.1rem + 4.2vw, 3.5rem);
  line-height: 1.05;
  letter-spacing: -0.035em;
  color: var(--text-hi);
  font-weight: 600;
}

.hero .kicker {
  display: block;
  margin-bottom: 1rem;
  font-size: 0.75rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
}

.hero .title {
  margin: 1rem 0 0;
  color: var(--text-hi);
  font-size: clamp(0.9375rem, 0.85rem + 0.4vw, 1.0625rem);
}
.hero .title .at { color: var(--muted); }

.hero .lede {
  margin: 1.25rem 0 0;
  color: var(--text);
  max-width: 54ch;
}
.hero .lede strong { color: var(--text-hi); font-weight: 600; }

/* ---------- tiles ---------- */

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: 0.375rem;
  overflow: hidden;
  margin: 0;
}
.tile {
  background: var(--bg-panel);
  padding: 1.125rem 1.125rem 1.25rem;
  transition: background 0.2s ease;
}
.tile:hover { background: var(--bg-raise); }
.tile dt {
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.5rem;
}
.tile dd {
  margin: 0;
  color: var(--text-hi);
  font-size: 0.9375rem;
  line-height: 1.45;
}

/* ---------- auth flow diagram ---------- */

.flow { list-style: none; margin: 0; padding: 0; counter-reset: step; }
.flow li {
  position: relative;
  padding: 0 0 1.75rem 3rem;
  counter-increment: step;
}
.flow li:last-child { padding-bottom: 0; }

.flow li::before {
  content: "";
  position: absolute;
  left: 0.9375rem;
  top: 1.9rem;
  bottom: -0.15rem;
  width: 1px;
  background: var(--line);
}
.flow li:last-child::before { display: none; }

.flow li::after {
  content: counter(step, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 0.1rem;
  width: 1.875rem;
  height: 1.875rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--accent-dim);
  border-radius: 50%;
  background: var(--accent-ghost);
  color: var(--accent);
  font-size: 0.6875rem;
}

.flow .step-name { display: block; color: var(--text-hi); margin-bottom: 0.25rem; }
.flow .step-detail { color: var(--muted); font-size: 0.8125rem; }
.flow .step-detail code {
  color: var(--text);
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 0.1875rem;
  padding: 0.05em 0.3em;
  font-size: 0.95em;
}

/* ---------- panels ---------- */

.panel {
  border: 1px solid var(--line);
  background: linear-gradient(180deg, var(--bg-panel), var(--bg));
  border-radius: 0.375rem;
  overflow: hidden;
}
.panel > header {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.625rem 1rem;
  border-bottom: 1px solid var(--line);
  background: var(--bg-raise);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.panel > header .lock { color: var(--accent); }
.panel > header .right { margin-left: auto; color: var(--accent); letter-spacing: 0.06em; }
.panel .body { padding: 1.375rem 1.25rem 1.5rem; }
.panel .body > p:first-child { margin-top: 0; }
.panel .body > p:last-child  { margin-bottom: 0; }
.panel + .panel { margin-top: 1.5rem; }

.kv {
  display: grid;
  grid-template-columns: 10rem 1fr;
  gap: 0.375rem 1rem;
  margin: 0;
  font-size: 0.8125rem;
}
.kv dt { color: var(--muted); }
.kv dd { margin: 0; color: var(--text); overflow-wrap: anywhere; }

/* ---------- actions ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.7rem 1.15rem;
  border: 1px solid var(--accent-dim);
  border-radius: 0.25rem;
  background: var(--accent-ghost);
  color: var(--accent);
  text-decoration: none;
  font: inherit;
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease,
              box-shadow 0.15s ease;
}
.btn:hover, .btn:focus-visible {
  background: rgba(64, 214, 168, 0.14);
  border-color: var(--accent);
  transform: translateY(-1px);
  box-shadow: 0 0.5rem 1.5rem -0.75rem rgba(64, 214, 168, 0.5);
}
.btn .arrow { transition: transform 0.15s ease; }
.btn:hover .arrow { transform: translateX(3px); }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
  margin: 1.5rem 0 0;
}
.btn-note { color: var(--muted); font-size: 0.75rem; }

a { color: var(--accent); text-underline-offset: 0.25em; text-decoration-color: var(--accent-dim); }
a:hover { text-decoration-color: var(--accent); }

:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; border-radius: 2px; }

/* ---------- project index ---------- */

.projects { list-style: none; margin: 0; padding: 0; }
.projects li + li { border-top: 1px solid var(--line); }

.projects a {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.25rem 1rem;
  padding: 1.125rem 1.25rem;
  text-decoration: none;
  color: inherit;
  transition: background 0.15s ease;
}
.projects a:hover { background: var(--bg-raise); }
.projects .name { color: var(--text-hi); }
.projects .desc { grid-column: 1 / -1; color: var(--muted); font-size: 0.8125rem; }
.projects .tag {
  color: var(--accent);
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  align-self: center;
  border: 1px solid var(--accent-dim);
  border-radius: 999px;
  padding: 0.1rem 0.6rem;
}
.projects .tag.test { color: var(--warn); border-color: rgba(224, 161, 69, 0.4); }
.projects .tag.live { color: var(--accent); border-color: rgba(64, 214, 168, 0.4); }
.projects .tag.wip  { color: var(--blue); border-color: rgba(74, 168, 240, 0.4); }

/* ---------- prose ---------- */

.prose { max-width: 70ch; }
.prose h1 {
  font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.125rem);
  letter-spacing: -0.025em;
  color: var(--text-hi);
  margin: 1.25rem 0 0;
}
.prose h2 {
  margin: 2.75rem 0 0.75rem;
  font-size: 1.0625rem;
  color: var(--text-hi);
  letter-spacing: -0.01em;
}
.prose h2::before { content: "## "; color: var(--accent-dim); }
.prose h3 { margin: 1.75rem 0 0.5rem; font-size: 0.9375rem; color: var(--text-hi); }
.prose code {
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 0.1875rem;
  padding: 0.1em 0.35em;
  font-size: 0.9em;
}
.prose pre {
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 0.375rem;
  padding: 1rem;
  overflow-x: auto;
}
.prose pre code { background: none; border: 0; padding: 0; }
.prose table { border-collapse: collapse; width: 100%; font-size: 0.8125rem; }
.prose th, .prose td { padding: 0.5rem 0.75rem; text-align: left; }

/* Header bands carry a top border AND a bottom border, with a 3px spacer row
   between the header and the first data row. See CLAUDE.md. */
.prose thead th {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  color: var(--muted);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 0.6875rem;
}
.prose tbody tr.spacer td { height: 3px; padding: 0; }
.prose tbody tr:not(.spacer):hover { background: var(--bg-panel); }
.prose .num { text-align: right; font-variant-numeric: tabular-nums; }

.callout {
  border: 1px solid rgba(74, 168, 240, 0.3);
  background: rgba(74, 168, 240, 0.06);
  border-radius: 0.375rem;
  padding: 1rem 1.125rem;
  margin: 1.5rem 0;
  font-size: 0.8125rem;
}
.callout strong { color: var(--blue); }

.backlink { font-size: 0.8125rem; color: var(--muted); text-decoration: none; }
.backlink:hover { color: var(--accent); }

/* ---------- motion and small screens ---------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .ocean { opacity: 1; }
}

@media (max-width: 34rem) {
  .kv { grid-template-columns: 1fr; gap: 0 0; }
  .kv dd { margin-bottom: 0.5rem; }
  .topbar .meta { display: none; }
  .site-footer .spacer { margin-left: 0; }
  .tagline { letter-spacing: 0.16em; }
  .enter { margin-top: 2.25rem; }
}

/* ==========================================================================
   WHOOP TRACKING
   Charts are inline SVG built by whoop.js. Everything is styled from here by
   class, because the CSP forbids style attributes - the JS therefore sets
   geometry attributes only, never presentation.
   ========================================================================== */

:root {
  --rec-green:  #40d6a8;
  --rec-yellow: #e0a145;
  --rec-red:    #e05a52;

  --stage-deep:  #2f6fb5;
  --stage-rem:   #6db2f2;
  --stage-light: #3c4d61;
}

.shell.wide { max-width: 84rem; }

.wt-status {
  margin: 1rem 0 0;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.wt-status.ok  { color: var(--accent); }
.wt-status.bad { color: var(--rec-red); }

/* ---------- layout ---------- */

.wt-grid-lead {
  display: grid;
  grid-template-columns: minmax(15rem, 1fr) minmax(20rem, 2fr);
  gap: 1.5rem;
}
.wt-grid-chart {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(15rem, 1fr);
  gap: 1.5rem;
  margin-top: 1.5rem;
}
.wt-grid-lead .panel + .panel,
.wt-grid-chart .panel + .panel { margin-top: 0; }

@media (max-width: 62rem) {
  .wt-grid-lead, .wt-grid-chart { grid-template-columns: 1fr; }
}

.panel .body.chart { padding: 1rem 0.75rem 0.5rem; }

.wt-legend { display: flex; gap: 0.9rem; margin-left: auto; }
.wt-key { color: var(--muted); font-size: 0.6875rem; letter-spacing: 0.04em; }
.wt-key::before {
  content: "";
  display: inline-block;
  width: 0.5rem; height: 0.5rem;
  margin-right: 0.35rem;
  border-radius: 1px;
  background: currentColor;
}
.wt-key.z-green  { color: var(--rec-green); }
.wt-key.z-yellow { color: var(--rec-yellow); }
.wt-key.z-red    { color: var(--rec-red); }
.wt-key.k-deep   { color: var(--stage-deep); }
.wt-key.k-rem    { color: var(--stage-rem); }
.wt-key.k-light  { color: var(--stage-light); }
.wt-key.k-bed    { color: var(--blue); }
.wt-key.k-wake   { color: var(--accent); }

.wt-empty { color: var(--muted); margin: 0; }

/* ---------- latest recovery ---------- */

.wt-latest { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.25rem 0.75rem; }
.wt-latest-score {
  font-size: clamp(3rem, 9vw, 4.5rem);
  line-height: 1;
  font-weight: 600;
  letter-spacing: -0.02em;
}
.wt-latest-unit { font-size: 1.25rem; color: var(--muted); }
.wt-latest.z-green  .wt-latest-score { color: var(--rec-green); }
.wt-latest.z-yellow .wt-latest-score { color: var(--rec-yellow); }
.wt-latest.z-red    .wt-latest-score { color: var(--rec-red); }

.wt-latest-meta { margin-left: auto; text-align: right; }
.wt-latest-zone {
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.6875rem;
}
.wt-latest.z-green  .wt-latest-zone { color: var(--rec-green); }
.wt-latest.z-yellow .wt-latest-zone { color: var(--rec-yellow); }
.wt-latest.z-red    .wt-latest-zone { color: var(--rec-red); }
.wt-latest-day { color: var(--text-hi); font-size: 0.8125rem; }
.wt-latest-sub { color: var(--muted); font-size: 0.75rem; white-space: pre; }

/* ---------- trailing average cards ---------- */

.wt-trail { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.75rem; }
.wt-trail-card {
  border: 1px solid var(--line);
  background: var(--bg-raise);
  padding: 0.85rem 0.9rem;
  border-radius: 2px;
  cursor: default;
}
.wt-trail-card:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; }
.wt-trail-label {
  color: var(--muted);
  font-size: 0.6875rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.wt-trail-value {
  font-size: 1.75rem;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
  color: var(--text-hi);
}
.wt-trail-card.z-green  .wt-trail-value { color: var(--rec-green); }
.wt-trail-card.z-yellow .wt-trail-value { color: var(--rec-yellow); }
.wt-trail-card.z-red    .wt-trail-value { color: var(--rec-red); }
.wt-trail-delta { font-size: 0.75rem; font-variant-numeric: tabular-nums; }
.wt-trail-delta.d-up   { color: var(--accent); }
.wt-trail-delta.d-down { color: var(--rec-red); }
.wt-trail-delta.d-flat { color: var(--muted); }

@media (max-width: 40rem) {
  .wt-trail { grid-template-columns: 1fr; }
}

/* ---------- svg ---------- */

.wt-svg { display: block; width: 100%; height: auto; overflow: visible; }
.wt-grid { stroke: var(--line-soft); stroke-width: 1; }
.wt-axis { fill: var(--muted); font-size: 9px; font-family: var(--mono); }
.wt-hit { fill: transparent; }
.wt-hit:focus-visible, .wt-bar:focus-visible, .wt-stack:focus-visible,
.wt-cons:focus-visible, .wt-scatter:focus-visible, .wt-zone:focus-visible {
  outline: 1px solid var(--accent);
}

.wt-bar { transition: opacity 0.12s ease; }
.wt-bar:hover { opacity: 0.75; }
.wt-bar.z-green  { fill: var(--rec-green); }
.wt-bar.z-yellow { fill: var(--rec-yellow); }
.wt-bar.z-red    { fill: var(--rec-red); }
.wt-missing { fill: var(--line); }

.wt-zoneline { stroke-width: 1; stroke-dasharray: 3 4; opacity: 0.55; }
.wt-zoneline.z-green  { stroke: var(--rec-green); }
.wt-zoneline.z-yellow { stroke: var(--rec-yellow); }

.wt-line { fill: none; stroke-width: 1.5; }
.wt-line-accent { stroke: var(--accent); }

.wt-sleep-met   { fill: var(--accent-dim); }
.wt-sleep-short { fill: var(--rec-red); opacity: 0.85; }
.wt-needline    { stroke: var(--text-hi); stroke-width: 1; opacity: 0.55; }

.wt-deep  { fill: var(--stage-deep); }
.wt-rem   { fill: var(--stage-rem); }
.wt-light { fill: var(--stage-light); }
.wt-stack:hover { opacity: 0.78; }

.wt-sleepspan { stroke: var(--line); stroke-width: 3; opacity: 0.7; }
.wt-dot-bed   { fill: var(--blue); }
.wt-dot-wake  { fill: var(--accent); }
.wt-cons:hover .wt-sleepspan { stroke: var(--accent-dim); }

.wt-scatter { opacity: 0.85; }
.wt-scatter.z-green  { fill: var(--rec-green); }
.wt-scatter.z-yellow { fill: var(--rec-yellow); }
.wt-scatter.z-red    { fill: var(--rec-red); }

.wt-zone.zn-0 { fill: #24303f; }
.wt-zone.zn-1 { fill: #2f6fb5; }
.wt-zone.zn-2 { fill: #40d6a8; }
.wt-zone.zn-3 { fill: #cbd25a; }
.wt-zone.zn-4 { fill: #e0a145; }
.wt-zone.zn-5 { fill: #e05a52; }
.wt-zone:hover { opacity: 0.8; }

/* ---------- tables ---------- */

/* Header band carries a top border AND a bottom border, and a 3px spacer row
   separates it from the first data row. House rule. The spacer is a real row
   rather than padding because padding does not survive a copy into a
   spreadsheet. */
.wt-table { border-collapse: collapse; width: 100%; font-size: 0.8125rem; }
.wt-table th, .wt-table td { padding: 0.4rem 0.6rem; text-align: left; }
.wt-table thead th {
  color: var(--muted);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 0.6875rem;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--bg-raise);
}
.wt-table tbody tr.spacer td { height: 3px; padding: 0; }
.wt-table tbody tr:not(.spacer):hover { background: var(--bg-raise); }
.wt-table tbody tr:focus-visible { outline: 1px solid var(--accent); }
.wt-table .num { text-align: right; font-variant-numeric: tabular-nums; }

.wt-chip {
  display: inline-block;
  min-width: 3.25rem;
  padding: 0.05rem 0.4rem;
  border: 1px solid var(--line);
  border-radius: 2px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.wt-chip.z-green  { color: var(--rec-green);  border-color: rgba(64, 214, 168, 0.35); }
.wt-chip.z-yellow { color: var(--rec-yellow); border-color: rgba(224, 161, 69, 0.35); }
.wt-chip.z-red    { color: var(--rec-red);    border-color: rgba(224, 90, 82, 0.35); }
.wt-chip.z-none   { color: var(--muted); }

/* ---------- key/value blocks ---------- */

.wt-kv {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.35rem 1.25rem;
  margin: 0;
  font-size: 0.8125rem;
}
.wt-kv dt { color: var(--muted); }
.wt-kv dd {
  margin: 0;
  color: var(--text-hi);
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: pre;
}

/* ---------- tooltip ---------- */

.wt-tip {
  position: fixed;
  z-index: 50;
  pointer-events: none;
  min-width: 11rem;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.55);
  padding: 0.5rem 0.6rem;
  font-size: 0.75rem;
  border-radius: 2px;
}
.wt-tip[hidden] { display: none; }
.wt-tip-head {
  color: var(--text-hi);
  border-bottom: 1px solid var(--line);
  padding-bottom: 0.3rem;
  margin-bottom: 0.35rem;
  letter-spacing: 0.04em;
}
.wt-tip-head.z-green  { color: var(--rec-green); }
.wt-tip-head.z-yellow { color: var(--rec-yellow); }
.wt-tip-head.z-red    { color: var(--rec-red); }
.wt-tip-rows {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.15rem 0.9rem;
  margin: 0;
}
.wt-tip-rows dt { color: var(--muted); }
.wt-tip-rows dd {
  margin: 0;
  text-align: right;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: reduce) {
  .wt-bar, .wt-stack, .wt-zone { transition: none; }
}
.wt-missing {
  color: var(--rec-red);
  border-left: 2px solid var(--rec-red);
  padding-left: 0.75rem;
  margin: 0 0 1rem;
}

/* ---------- WHOOP: four trailing cards, sleep lines ---------- */

/* Four windows now: 7 / 30 / 90 / 365. Two-up before one-up, so the pairs stay
   comparable on a narrow screen rather than becoming a single tall column. */
.wt-trail { grid-template-columns: repeat(4, 1fr); }

@media (max-width: 62rem) {
  .wt-trail { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 30rem) {
  .wt-trail { grid-template-columns: 1fr; }
}

/* Sleep need is the reference, so it reads as a rule rather than a series:
   thin, dashed, unsaturated. The slept line sits on top of it in colour. */
.wt-line-need {
  stroke: var(--muted);
  stroke-width: 1;
  stroke-dasharray: 4 3;
  opacity: 0.85;
}

.wt-line-slept {
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* Gradient stops. stop-color is a CSS property as well as a presentation
   attribute, which is what lets the palette stay in this file instead of being
   duplicated as hex literals inside whoop.js. */
.wt-stop.z-green  { stop-color: var(--rec-green); }
.wt-stop.z-yellow { stop-color: var(--rec-yellow); }
.wt-stop.z-red    { stop-color: var(--rec-red); }
.wt-stop.z-none   { stop-color: var(--line); }

.wt-night-dot.z-green  { fill: var(--rec-green); }
.wt-night-dot.z-yellow { fill: var(--rec-yellow); }
.wt-night-dot.z-red    { fill: var(--rec-red); }
.wt-night-dot.z-none   { fill: var(--muted); }
.wt-night:hover .wt-night-dot { r: 3.2; }
.wt-key.k-need { color: var(--muted); }
.wt-key.k-need::before { border-radius: 0; height: 0.15rem; }

/* ==========================================================================
   LIGHTS - clickable floorplan (/projects/lights/)
   Geometry lives in lights.js; every colour, stroke and font lives here
   (rule 2 - no inline styles anywhere). SVG lengths are user units (feet);
   wall strokes carry vector-effect="non-scaling-stroke" so they stay 1px.
   ========================================================================== */

.fp-controls { margin-bottom: 0.5rem; }
.fp-controls .btn[aria-pressed="true"] {
  color: var(--accent);
  border-color: var(--accent-dim);
  background: var(--accent-ghost);
}

.fp-canvas { max-width: 46rem; margin: 0 auto; }
.fp-canvas svg { display: block; width: 100%; height: auto; }

.fp-room  { fill: var(--bg-raise); stroke: #223044; }
.fp-inner { fill: none; stroke: #223044; }
.fp-solid { fill: #2e4258; stroke: none; }
.fp-pillar { fill: #2e4258; stroke: none; }
.fp-open   { stroke: var(--bg-raise); stroke-width: 3px; }
.fp-edge  { fill: none; stroke: var(--accent-dim); }
.fp-stair { stroke: #223044; }
.fp-void  { fill: none; stroke: #223044; stroke-dasharray: 0.5 0.35; }
.fp-door  { stroke: var(--accent); }
.fp-garage-door { stroke: #2e4258; stroke-dasharray: 0.6 0.4; }

.fp-label {
  fill: var(--muted);
  font-family: var(--mono);
  font-size: 0.52px;            /* svg user units, not screen px */
  letter-spacing: 0.05px;
  text-anchor: middle;
  pointer-events: none;
  user-select: none;
}
.fp-compass {
  fill: var(--muted);
  font-family: var(--mono);
  font-size: 0.46px;
  letter-spacing: 0.08px;
  text-anchor: middle;
  opacity: 0.7;
}

.fp-light { cursor: pointer; outline: none; }
.fp-light .hit  { fill: transparent; stroke: none; pointer-events: all; }
.fp-light .halo { fill: var(--accent); opacity: 0; filter: blur(0.9px); transition: opacity 0.25s ease; }
.fp-light .bulb { fill: var(--bg-panel); stroke: var(--muted); transition: fill 0.2s ease, stroke 0.2s ease; }
.fp-light:hover .bulb { stroke: var(--text-hi); }
.fp-light:focus-visible .hit { stroke: var(--blue); }
.fp-light.on .halo { opacity: 0.5; }
.fp-light.on .bulb { fill: var(--accent); stroke: var(--accent); }

.fp-note { color: var(--muted); font-size: 0.8125rem; margin: 1rem 0 0; }

@media (prefers-reduced-motion: reduce) {
  .fp-light .halo, .fp-light .bulb { transition: none; }
}
