/* home_styles.css — layout for the public marketing page.
 *
 * DELIBERATELY NO COLOURS OR TYPEFACES OF ITS OWN. Every value below is a var() from
 * shared_styles.css, so the public site and the signed-in app share one palette, one type
 * scale and one dark theme. Change the product's tokens and this page follows; there is no
 * second copy to drift. A test fails the build if a literal colour ever appears in this file.
 *
 * v0.576 PUBLIC VOICE: the page carries BOTH copy voices in its markup (data-voice="butler" /
 * data-voice="plain"); the server stamps data-home-voice on <html> from the Admin -> Branding
 * home_voice setting, and these two rules show exactly one voice. display:none also removes
 * the inactive copy from the accessibility tree, so screen readers hear one voice too.
 *
 * Everything is prefixed .hm- so it cannot collide with the app's component classes — this
 * stylesheet loads alongside shared_styles.css, not instead of it.
 *
 * The design is a paper-and-engraving reading of the app's own palette. That is not a
 * coincidence: the tokens were already warm paper, near-black ink and evergreen, so the look
 * is DERIVED from the product rather than imposed on it.
 *
 * DEPTH IS THE POINT OF THIS PAGE, built three ways, each doing a different job:
 *   1. a WebGL contour surface behind the hero  — atmosphere, ignorable, never load-bearing
 *   2. a real perspective well around the chart — the product itself, given physical presence
 *   3. lift on cards and tiers                  — ordinary affordance, so hover means something
 * All three collapse under prefers-reduced-motion, and none carries information the text does
 * not also carry.
 */

body.home { background: var(--bg); color: var(--text); }
body.home main { display: block; }

/* v0.576: the public-voice switch (see header note). */
html[data-home-voice="butler"] [data-voice="plain"] { display: none; }
html[data-home-voice="plain"] [data-voice="butler"] { display: none; }

body.home {
  /* Local, NON-COLOUR additions. A monospace stack is not among the shared tokens because no
     signed-in surface needed one; the figures on this page do. */
  --hm-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* The allocation ramp is DERIVED from the palette rather than picked, so a rebrand carries
     it and the dark theme does not have to be hand-tuned to match. */
  --hm-ramp-1: var(--primary);
  --hm-ramp-2: var(--success);
  --hm-ramp-3: color-mix(in srgb, var(--primary) 42%, var(--surface));
  --hm-ramp-4: var(--warning);
  --hm-ramp-5: color-mix(in srgb, var(--danger) 32%, var(--surface));
}

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

.hm-wrap { max-width: 1120px; margin: 0 auto; padding: 0 clamp(1.15rem, 4vw, 2.6rem); }
body.home h1, body.home h2, body.home h3 { text-wrap: balance; }
.hm-num, .hm-sheet-v, .hm-amt, .hm-v, .hm-tnum { font-variant-numeric: tabular-nums; }

.hm-lbl {
  font-size: .66rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--primary); font-weight: 700; margin: 0;
}
.hm-quiet { color: var(--text-faint); }

/* ---------------------------------------------------------------- buttons */
.hm-btn {
  font: inherit; font-size: .87rem; text-decoration: none; display: inline-block;
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
  padding: .58rem 1.15rem; border-radius: var(--radius-sm); cursor: pointer;
  transition: border-color var(--transition), color var(--transition),
              background var(--transition);
  white-space: nowrap;
}
.hm-btn:hover { border-color: var(--primary); color: var(--primary); }
.hm-btn-primary {
  background: var(--primary); border-color: var(--primary); color: var(--on-primary);
  font-weight: 500; box-shadow: var(--shadow-sm);
}
.hm-btn-primary:hover {
  background: var(--primary-hover); border-color: var(--primary-hover); color: var(--on-primary);
}
.hm-btn-lg { font-size: .95rem; padding: .74rem 1.5rem; }
.hm-btn-block { display: block; text-align: center; }
.hm-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

/* ---------------------------------------------------------------- nav */
.hm-nav {
  position: sticky; top: 0; z-index: 40; border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(170%) blur(14px);
}
.hm-nav-in { display: flex; align-items: center; gap: 1.7rem; height: 66px; }
/* Mark + name sized up 75% at the owner's request, matching the in-app header. */
/* Mark only — the wordmark beside it retired, so the type properties that existed to set
   it (display face, size, tracking) and the gap that separated the two went with it. The
   name still sits inside, visually hidden for the accessible name, which needs none of
   them. The MARK's own size lives on .hm-diamond / .hm-logo-img below. */
.hm-mark {
  margin-right: auto; display: flex; align-items: center;
  text-decoration: none; color: var(--text);
}
.hm-diamond {
  width: 23px; height: 23px; border: 2.8px solid var(--primary); border-radius: 5px;
  transform: rotate(45deg); flex: none;
}
/* v0.555: a custom uploaded logo replaces the diamond (server-swapped in _decorate_home). */
.hm-logo-img { width: 39px; height: 39px; object-fit: contain; flex: none; }
.hm-links { display: flex; gap: 1.5rem; font-size: .87rem; }
.hm-links a { color: var(--text-muted); text-decoration: none; }
.hm-links a:hover { color: var(--text); }
@media (max-width: 900px) { .hm-links { display: none; } }

/* Theme toggle (v0.583) — the same convention as the in-app switch: in dark you see the
   sun (what a click switches TO), in light the moon. The swap is pure CSS off
   html[data-theme], so the right icon shows on first paint before any script runs. */
.hm-theme {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; padding: 0; flex: none;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: transparent; color: var(--muted); cursor: pointer;
}
.hm-theme:hover { color: var(--text); border-color: var(--text); }
.hm-theme svg { width: 18px; height: 18px; }
.hm-theme .hm-th-sun { display: none; }
html[data-theme="dark"] .hm-theme .hm-th-sun { display: block; }
html[data-theme="dark"] .hm-theme .hm-th-moon { display: none; }
/* The 44px coarse-pointer floor (v0.571) applies to the public page too. */
@media (pointer: coarse) { .hm-theme { width: 44px; height: 44px; } }
/* Narrow screens: the row (mark + buttons + toggle) must never push past the viewport —
   measured overflowing at phone widths once the toggle joined. Tighten the nav's own
   spacing (scoped, so the hero CTAs keep their size), and below 480px drop the "Log in"
   shortcut: the primary CTA leads to the auth panel, which offers sign-in right there. */
@media (max-width: 560px) {
  .hm-nav-in { gap: .7rem; }
  .hm-nav-in .hm-btn { padding: .5rem .8rem; }
}
/* v0.594: the ≤480px rule that dropped the header's "Log in" shortcut retired with the
   button itself — the header now carries one CTA, which fits at every width. The FOOTER
   still has an explicit "Log in" link and is unaffected. */

/* ---------------------------------------------------------------- hero */
.hm-hero { position: relative; overflow: hidden; border-bottom: 1px solid var(--border); }
#hm-gl { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

/* A READING SCRIM, not a wash. It protects the left column where the headline sits and gets
   out of the way entirely across the right, so the surface is genuinely present rather than a
   texture you have to hunt for. */
.hm-veil {
  position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(100deg,
      var(--bg) 0%, var(--bg) 30%,
      color-mix(in srgb, var(--bg) 72%, transparent) 46%,
      color-mix(in srgb, var(--bg) 10%, transparent) 68%, transparent 82%),
    linear-gradient(to bottom,
      var(--bg) 0%, transparent 14%, transparent 88%, var(--bg) 100%);
}
@media (max-width: 860px) {
  /* On a phone the copy spans the width, so the scrim has to as well. */
  .hm-veil {
    background: linear-gradient(to bottom,
      var(--bg) 0%, color-mix(in srgb, var(--bg) 86%, transparent) 40%,
      color-mix(in srgb, var(--bg) 55%, transparent) 72%, var(--bg) 100%);
  }
}
.hm-hero-in {
  position: relative; z-index: 3;
  /* LONGHAND, deliberately. This element is also .hm-wrap, and a `padding` shorthand here
     would reset the wrap's horizontal padding to 0 — same specificity, but this rule comes
     later, so it wins and the hero alone runs edge-to-edge while every other section stays
     inset. Only the block padding is this rule's business. */
  padding-top: clamp(3.2rem, 8vw, 6.5rem);
  padding-bottom: clamp(2.4rem, 5vw, 4rem);
}
.hm-hero h1 {
  font-family: var(--font-display); font-weight: 400; margin: 1rem 0 0;
  font-size: clamp(2.3rem, 6.4vw, 4.5rem); line-height: 1.02; letter-spacing: -.032em;
}
.hm-hero h1 em { font-style: italic; color: var(--primary); }
/* Each headline line is a HARD single line — all of line 1 on line 1, all of line 2 on
   line 2, never a third. The fitters (inline first-paint + app_home.js) scale the font
   so the widest line, including each roll's widest option, always fits. */
.hm-hero h1 .hm-hline { display: block; white-space: nowrap; }
/* Section C rides inside the glue so the closing mark can never wrap onto a line of its
   own; on line 2 that puts it inside the em, so style it back to the heading. */
.hm-glue { white-space: nowrap; }
/* The roll window reserves .06em of padding (so an italic option's overhang isn't
   clipped by overflow:hidden) plus the driver's 1px rounding guard. Both are LAYOUT
   room, not typography: cancel them here so the closing mark sits tight against the
   word, exactly as an adjacent character should. */
.hm-hero h1 .hm-secc {
  font-style: normal; color: var(--text); margin-left: calc(-0.06em - 1px);
}
/* The rolling Section B window: a one-line viewport the option stack slides through.
   app_home.js measures the real baseline delta and corrects vertical-align (an
   overflow-hidden inline-block loses its text baseline — the bottom edge becomes it). */
.hm-roll {
  display: inline-block; overflow: hidden; height: 1.18em; vertical-align: -0.14em;
  transition: width .5s cubic-bezier(.2, .75, .25, 1);
}
.hm-roll.hm-measuring { transition: none; }   /* mid-transition widths poison measurement */
.hm-stack { display: block; }
/* width: max-content — each option reports its OWN text width even after the window is
   given an explicit px width, so the window can hug whichever option is resting. The
   fixed line-height keeps every option's glyph box inside its 1.18em row. */
.hm-stack > span {
  display: block; width: max-content; height: 1.18em; line-height: 1.18;
  white-space: nowrap; padding-right: .06em;
}
.hm-roll.hm-sweeping .hm-stack {
  transition: transform var(--hm-sweep, 700ms) cubic-bezier(.22, .8, .26, 1);
}
/* Reduced-motion visitors always see the resting option — the server pre-positions it,
   app_home.js skips the animation, and this kills any transition that could still fire. */
@media (prefers-reduced-motion: reduce) {
  .hm-roll, .hm-roll .hm-stack { transition: none; }
}
.hm-lede {
  max-width: 46ch; margin: 1.3rem 0 0; color: var(--text-muted);
  font-size: clamp(1rem, 1.6vw, 1.13rem);
}
.hm-cta { display: flex; gap: .7rem; margin-top: 2rem; flex-wrap: wrap; }
.hm-note { margin-top: 1.1rem; font-size: .82rem; color: var(--text-faint); }

.hm-readout {
  display: flex; gap: clamp(1.4rem, 4vw, 3.4rem); flex-wrap: wrap;
  margin-top: clamp(2.4rem, 5vw, 3.6rem); padding-top: 1.5rem;
  border-top: 1px solid var(--border-strong);
  /* Alfred's anchor: he is this block's absolute child, so bottom:100% seats him
     exactly on the rule above at every viewport. */
  position: relative;
}
.hm-readout .k {
  font-size: .64rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--text-faint); font-weight: 700; margin: 0;
}
.hm-readout .v {
  font-family: var(--font-display); font-size: clamp(1.3rem, 3.2vw, 1.9rem);
  letter-spacing: -.022em; margin: .18rem 0 0; font-variant-numeric: tabular-nums;
}
.hm-readout .v.up { color: var(--primary); }
.hm-live {
  display: inline-flex; align-items: center; gap: .45rem; font-family: var(--hm-mono);
  font-size: .66rem; color: var(--text-muted); border: 1px solid var(--border-strong);
  border-radius: 999px; padding: .26rem .72rem; background: var(--surface);
}
.hm-live i {
  width: 6px; height: 6px; border-radius: 50%; background: var(--primary); display: block;
  animation: hm-pulse 2.6s ease-in-out infinite;
}
@keyframes hm-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .22; } }
@media (prefers-reduced-motion: reduce) { .hm-live i { animation: none; } }

/* ------------------------------------------------------------- Alfred, the butler */
/* Canonical character (assets/alfred.svg + the character spec). He stands on the
   hero's engraved landscape: above the canvas and veil, below the copy, purely
   decorative. Ids/keyframes carry an alf- prefix (shared page namespace); every
   motion value is the spec's, verbatim — expressive tier, as approved. */
/* Anchored to the readout: bottom:100% is the rule line itself; the small translate
   seats the ground shadow ON the line rather than the viewBox's empty margin (the
   shadow bottoms 10 of 452 units above the box edge). Negative z paints him behind
   the hero copy while staying above the canvas and veil. */
.hm-alfred { position: absolute; z-index: -1; pointer-events: none;
             bottom: 100%; right: clamp(0rem, 3vw, 2.5rem);
             width: clamp(250px, 26vw, 380px);
             transform: translateY(2.2%); }
.hm-alfred svg { display: block; width: 100%; height: auto; }
/* Dark ground: the navy suit sits close to midnight, so the spec's own brass halo
   does the separating — one step brighter. No fill changes, no glows, no shadows.
   Applies to both renditions of him. */
html[data-theme="dark"] .hm-alfred .alf-halo-fill,
html[data-theme="dark"] .hm-alfred-m .alf-halo-fill { opacity: .11; }
html[data-theme="dark"] .hm-alfred .alf-halo-ring,
html[data-theme="dark"] .hm-alfred-m .alf-halo-ring { opacity: .32; }
/* Narrow screens: the animated figure yields to a small static twin woven into the
   lede — the text wraps around him instead of losing him entirely. */
.hm-alfred-m { display: none; }
@media (max-width: 980px) {
  .hm-alfred { display: none; }
  .hm-alfred-m { display: block; float: right;
                 width: clamp(104px, 30vw, 150px); height: auto;
                 margin: .15rem 0 .5rem .9rem; }
}

.hm-alfred g { transform-box: view-box; }
#alf-entr { animation: alf-enter .7s ease-out both; }
#alf-fig { animation: alf-breathe 4.6s ease-in-out infinite; transform-origin: 190px 442px; }
#alf-head { animation: alf-headkf 9s ease-in-out infinite; transform-origin: 190px 168px; }
#alf-eyes { animation: alf-glance 9s ease-in-out infinite; }
#alf-eyeL { animation: alf-blink 6.4s infinite; transform-origin: 175px 122px; }
#alf-eyeR { animation: alf-blink 6.4s infinite .12s; transform-origin: 205px 120px; }
#alf-browR { animation: alf-browR 9s ease-in-out infinite; }
#alf-browL { animation: alf-browL 9s ease-in-out infinite; }
#alf-stache { animation: alf-stache 9s ease-in-out infinite; transform-origin: 190px 148px; }
#alf-dropcoin { animation: alf-drop 9s cubic-bezier(.5,0,.8,1) infinite; }
#alf-coinstack { animation: alf-squash 9s ease-out infinite; transform-origin: 174px 272px; }
#alf-bellg { animation: alf-ring 11s ease-in-out infinite; transform-origin: 214px 270px; }
#alf-r1 { animation: alf-wave1 11s ease-out infinite; transform-origin: 214px 248px; transform-box: view-box; }
#alf-r2 { animation: alf-wave2 11s ease-out infinite; transform-origin: 214px 248px; transform-box: view-box; }
#alf-chainv { animation: alf-sway 3.2s ease-in-out infinite; transform-origin: 190px 284px; }
#alf-glare { animation: alf-glint 7s ease-in-out infinite; }
@keyframes alf-enter { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
@keyframes alf-breathe { 0%,100% { transform: scale(1,1); } 50% { transform: scale(1.005,1.011); } }
@keyframes alf-headkf { 0%,16%,26%,76%,100% { transform: rotate(0) translateY(0); } 20% { transform: rotate(-1.3deg); } 82%,88% { transform: rotate(1.6deg); } 90% { transform: rotate(1.6deg) translateY(2.5px); } 92.5% { transform: rotate(.8deg) translateY(0); } 95% { transform: rotate(.4deg) translateY(2px); } 97% { transform: rotate(0) translateY(0); } }
@keyframes alf-glance { 0%,76%,97%,100% { transform: translate(0,0); } 80%,94% { transform: translate(3px,3px); } }
@keyframes alf-blink { 0%,42%,48%,86%,91.5%,93%,98%,100% { transform: scaleY(1); } 44%,46% { transform: scaleY(.08); } 88%,90% { transform: scaleY(.08); } 94.5%,96.5% { transform: scaleY(.08); } }
@keyframes alf-browR { 0%,76%,94%,100% { transform: translateY(0); } 79%,90% { transform: translateY(-2.5px); } }
@keyframes alf-browL { 0%,76%,94%,100% { transform: translateY(0); } 79%,90% { transform: translateY(-1.2px); } }
@keyframes alf-stache { 0%,95%,100% { transform: scaleX(1); } 96.5% { transform: scaleX(1.05); } 98% { transform: scaleX(.98); } }
@keyframes alf-drop { 0%,76% { transform: translateY(-48px); opacity: 0; } 78% { transform: translateY(-48px); opacity: 1; } 85% { transform: translateY(0); } 87% { transform: translateY(-4px); } 89%,96% { transform: translateY(0); opacity: 1; } 99%,100% { transform: translateY(0); opacity: 0; } }
@keyframes alf-squash { 0%,84%,89%,100% { transform: scaleY(1); } 86% { transform: scaleY(.93); } }
@keyframes alf-ring { 0%,80%,93%,100% { transform: rotate(0); } 82% { transform: rotate(-6deg); } 85% { transform: rotate(5deg); } 88% { transform: rotate(-3deg); } 91% { transform: rotate(2deg); } }
@keyframes alf-wave1 { 0%,80% { transform: scale(.3); opacity: 0; } 82% { opacity: .5; } 94%,100% { transform: scale(1.9); opacity: 0; } }
@keyframes alf-wave2 { 0%,83% { transform: scale(.3); opacity: 0; } 85% { opacity: .45; } 97%,100% { transform: scale(1.9); opacity: 0; } }
@keyframes alf-sway { 0%,100% { transform: rotate(-3deg); } 50% { transform: rotate(3deg); } }
@keyframes alf-glint { 0%,88%,100% { opacity: .18; } 93% { opacity: .5; } }
@media (prefers-reduced-motion: reduce) {
  .hm-alfred svg g, .hm-alfred svg polygon, .hm-alfred svg circle { animation: none !important; }
  #alf-entr { opacity: 1; }
}

/* ---------------------------------------------------------------- sections */
.hm-s { padding: clamp(3.2rem, 7vw, 5.5rem) 0; border-bottom: 1px solid var(--border); }
.hm-alt { background: var(--surface-2); }
.hm-s h2 {
  font-family: var(--font-display); font-weight: 400; margin: .8rem 0 0;
  font-size: clamp(1.75rem, 3.6vw, 2.6rem); line-height: 1.1; letter-spacing: -.028em;
}
.hm-head { max-width: 56ch; }
.hm-head > p { color: var(--text-muted); margin: 1rem 0 0; }
.hm-head .hm-caveat { font-size: .86rem; color: var(--text-faint); }

/* ---------------------------------------------------------------- the net-worth chart */
/* The chart sits in its own perspective well. Tilt is pointer-driven and small — enough that
   the card has physical presence, never enough to make figures hard to read. */
.hm-stage { perspective: 1600px; perspective-origin: 50% 40%; }
.hm-chart {
  margin-top: clamp(1.8rem, 4vw, 2.8rem); background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden;
  transform-style: preserve-3d; will-change: transform;
  /* A RESTING angle, so the card is dimensional on sight rather than only once you interact
     with it — which also means the depth survives a device with no pointer at all. */
  transform: rotateX(2.4deg) rotateY(-4.2deg);
  transition: box-shadow .3s ease, transform .5s cubic-bezier(.2, .8, .3, 1);
  box-shadow: var(--lift-3);
}
.hm-chart:hover {
  box-shadow: var(--lift-4);
}
/* The plotted line lifts off the card face — the one place literal Z reads as meaning, because
   the line IS the subject and the grid behind it is not. */
.hm-chart-body svg { transform: translateZ(26px); display: block; width: 100%; height: auto; }
.hm-chart-top, .hm-chart-foot { transform: translateZ(10px); }
@media (prefers-reduced-motion: reduce) {
  .hm-chart { transform: none !important; }
  .hm-chart-body svg, .hm-chart-top, .hm-chart-foot { transform: none; }
}
.hm-chart-top {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 1.5rem;
  flex-wrap: wrap; padding: 1.2rem clamp(1.1rem, 3vw, 1.8rem) .6rem;
}
.hm-chart-val {
  font-family: var(--font-display); font-size: clamp(1.9rem, 5vw, 2.9rem);
  letter-spacing: -.03em; line-height: 1; font-variant-numeric: tabular-nums; margin: .3rem 0 0;
}
.hm-chart-delta {
  font-size: .86rem; color: var(--primary); font-weight: 600; margin: .35rem 0 0;
}
.hm-legend {
  display: flex; gap: 1.1rem; font-size: .76rem; color: var(--text-muted); flex-wrap: wrap;
}
.hm-legend span { display: flex; align-items: center; gap: .42rem; }
.hm-swatch { width: 16px; height: 3px; border-radius: 2px; display: block; }
.hm-sw-mine { background: var(--primary); }
.hm-sw-bench { background: var(--border-strong); }
.hm-chart-body { padding: 0 clamp(.6rem, 2vw, 1.1rem) .5rem; }
.hm-chart-foot {
  display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  padding: .85rem clamp(1.1rem, 3vw, 1.8rem) 1.1rem; border-top: 1px solid var(--border);
  font-size: .78rem; color: var(--text-faint);
}

/* The SVG is styled from HERE, not from presentation attributes on the elements, so it follows
   the theme. Hardcoded strokes would have been invisible the moment dark mode was switched on. */
.hm-plot-grid { stroke: var(--border); stroke-width: 1; }
.hm-plot-axis { fill: var(--text-faint); font-size: 11px; font-family: var(--hm-mono); }
.hm-plot-axis-x { fill: var(--text-faint); font-size: 11px; font-family: var(--font-body); }
.hm-plot-bench {
  fill: none; stroke: var(--border-strong); stroke-width: 2;
  stroke-linejoin: round; stroke-linecap: round; stroke-dasharray: 5 4;
}
.hm-plot-fill { fill: var(--primary); opacity: .13; }
.hm-plot-line {
  fill: none; stroke: var(--primary); stroke-width: 2.6;
  stroke-linejoin: round; stroke-linecap: round;
}
.hm-plot-vertex { fill: var(--surface); stroke: var(--primary); stroke-width: 2; }
.hm-plot-halo { fill: var(--primary); opacity: .14; }
.hm-plot-end { fill: var(--primary); stroke: var(--surface); stroke-width: 2; }
.hm-plot-drop { stroke: var(--border-strong); stroke-width: 1; stroke-dasharray: 3 3; }
.hm-plot-note { fill: var(--surface); stroke: var(--border); }
.hm-plot-note-k { fill: var(--text-faint); font-size: 10.5px; font-family: var(--font-body); }
.hm-plot-note-v { fill: var(--danger); font-size: 11px; font-family: var(--hm-mono); }

/* allocation + movers, under the chart */
.hm-under {
  display: grid; grid-template-columns: 1.1fr 1fr; gap: clamp(1rem, 2.6vw, 1.8rem);
  margin-top: clamp(1rem, 2.6vw, 1.5rem);
}
@media (max-width: 820px) { .hm-under { grid-template-columns: 1fr; } }
.hm-mini {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 1.1rem clamp(1rem, 2.6vw, 1.4rem);
  transition: transform .28s cubic-bezier(.2, .8, .3, 1), box-shadow .28s;
  box-shadow: var(--lift-1);
}
.hm-mini:hover {
  transform: translate3d(0, -4px, 0);
  box-shadow: var(--lift-2);
}
@media (prefers-reduced-motion: reduce) { .hm-mini:hover { transform: none; } }
.hm-mini h3 { margin: 0 0 .85rem; font-size: .84rem; font-weight: 600; }

.hm-alloc {
  display: flex; height: 9px; border-radius: 5px; overflow: hidden; background: var(--surface-2);
}
.hm-alloc i { display: block; height: 100%; }
.hm-alloc-key { display: grid; gap: .42rem; margin-top: .9rem; }
.hm-alloc-key > div {
  display: grid; grid-template-columns: 12px 1fr auto auto; gap: .6rem; align-items: center;
  font-size: .82rem; padding-bottom: .38rem; border-bottom: 1px solid var(--border);
}
.hm-alloc-key .sw { width: 10px; height: 10px; border-radius: 3px; }
.hm-alloc-key .pc {
  color: var(--text-faint); font-variant-numeric: tabular-nums; font-size: .76rem;
}
.hm-alloc-key .am { font-variant-numeric: tabular-nums; }
/* The net line is the sum of everything above it, so it is ruled off like one. */
.hm-alloc-key .hm-alloc-net {
  border-bottom: 0; border-top: 1px solid var(--border-strong);
  padding-top: .42rem; margin-top: .1rem; font-weight: 600;
}
.hm-r1 { background: var(--hm-ramp-1); }
.hm-r2 { background: var(--hm-ramp-2); }
.hm-r3 { background: var(--hm-ramp-3); }
.hm-r4 { background: var(--hm-ramp-4); }
.hm-r5 { background: var(--hm-ramp-5); }

.hm-hold { display: grid; gap: .1rem; }
.hm-hold > div {
  display: grid; grid-template-columns: 1fr auto auto; gap: .9rem; align-items: baseline;
  padding: .42rem 0; border-bottom: 1px solid var(--border); font-size: .84rem;
}
.hm-hold .sym { font-weight: 600; }
.hm-hold .sym small {
  display: block; font-weight: 400; color: var(--text-faint); font-size: .72rem;
}
.hm-hold .amt { font-variant-numeric: tabular-nums; }
.hm-hold .chg { font-variant-numeric: tabular-nums; font-size: .78rem; color: var(--primary); }
.hm-hold .chg.dn { color: var(--danger); }

.hm-mkt { display: flex; flex-wrap: wrap; gap: .45rem; margin-top: 1.4rem; }
.hm-chip {
  font-size: .74rem; border: 1px solid var(--border-strong); border-radius: 999px;
  padding: .26rem .72rem; color: var(--text-muted); background: var(--surface);
}
.hm-chip.on { border-color: var(--primary); color: var(--primary); font-weight: 600; }

/* ---------------------------------------------------------------- feature grid + rows */
.hm-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
  gap: clamp(1.4rem, 3vw, 2.4rem); margin-top: clamp(2rem, 4vw, 3rem);
}
.hm-grid h3 { font-size: 1rem; font-weight: 600; margin: 0 0 .4rem; }
.hm-grid p { font-size: .89rem; color: var(--text-muted); margin: 0; }
/* Numbered ONLY where the content is genuinely an enumerated set, never as decoration. */
.hm-grid .n {
  font-family: var(--hm-mono); font-size: .68rem; color: var(--primary);
  display: block; margin-bottom: .5rem;
}

.hm-rows { margin-top: clamp(1.8rem, 4vw, 2.6rem); border-top: 1px solid var(--border-strong); }
.hm-rows > div {
  display: grid; grid-template-columns: 13rem 1fr; gap: 1.4rem; padding: .82rem 0;
  border-bottom: 1px solid var(--border); font-size: .9rem;
}
@media (max-width: 660px) { .hm-rows > div { grid-template-columns: 1fr; gap: .12rem; } }
.hm-rows dt { font-weight: 600; }
.hm-rows dd { margin: 0; color: var(--text-muted); }

/* ---------------------------------------------------------------- two-up + panels */
.hm-two {
  display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.6rem, 4vw, 3.4rem);
  align-items: center;
}
@media (max-width: 860px) { .hm-two { grid-template-columns: 1fr; } }
/* Panels sit in perspective too, tilted very slightly away — they are supporting evidence
   beside the argument, and the angle says so without needing a caption. */
.hm-panel-stage { perspective: 1400px; }
.hm-panel {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  overflow: hidden; transform: rotateY(-3.2deg) rotateX(1.2deg);
  transition: transform .4s cubic-bezier(.2, .8, .3, 1), box-shadow .4s;
  box-shadow: var(--lift-3);
}
.hm-panel-stage.rev .hm-panel { transform: rotateY(3.2deg) rotateX(1.2deg); }
.hm-panel-stage:hover .hm-panel {
  transform: rotateY(0deg) rotateX(0deg) translate3d(0, -3px, 0);
  box-shadow: var(--lift-4);
}
@media (prefers-reduced-motion: reduce) {
  .hm-panel, .hm-panel-stage.rev .hm-panel, .hm-panel-stage:hover .hm-panel { transform: none; }
}
/* When the two-up stacks on a phone the panel must lead or follow DELIBERATELY, not by
   whichever order the markup happened to need on a wide screen. */
@media (max-width: 860px) { .hm-order1 { order: 1; } .hm-order2 { order: 2; } }
.hm-panel-h {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: .8rem 1.05rem; background: var(--surface-2); border-bottom: 1px solid var(--border);
}
.hm-r {
  display: flex; justify-content: space-between; gap: 1rem; padding: .62rem 1.05rem;
  border-bottom: 1px solid var(--border); font-size: .86rem;
}
.hm-r:last-child { border-bottom: 0; }
.hm-r .hm-v { color: var(--text-muted); font-variant-numeric: tabular-nums; }
.hm-r.hm-total { background: var(--primary-soft); }
.hm-r.hm-total > span:first-child { font-weight: 600; }
.hm-r.hm-total .hm-v { color: var(--primary); font-weight: 600; }
.hm-off { color: var(--text-faint); font-size: .78rem; }
.hm-ok { color: var(--primary); font-size: .78rem; font-weight: 600; }

/* ---------------------------------------------------------------- pricing */
/* ONE ROW, ALWAYS. However many plans the operator configures, they stay on a single
   horizontal line and the row scrolls — comparing tiers means seeing them side by side, and a
   grid that wraps the fourth plan onto its own row buries it.

   The vertical padding is not decoration: setting overflow-x also makes overflow-y a scroll
   container, so the highlighted tier's -8px lift and its shadow would be CLIPPED (and would
   raise a spurious vertical scrollbar) without room to move into. */
.hm-tiers {
  display: flex; gap: 1rem; margin-top: clamp(2rem, 4vw, 2.8rem);
  overflow-x: auto; overflow-y: hidden;
  padding: 16px 2px 20px;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
}
.hm-tier {
  /* Grow to share the width when there are only two or three, never shrink below a readable
     column, and cap the width so a lone plan is a card rather than a banner. */
  flex: 1 0 240px; max-width: 320px; scroll-snap-align: start;
  border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface);
  padding: 1.5rem; display: flex; flex-direction: column;
  transition: transform .28s cubic-bezier(.2, .8, .3, 1), box-shadow .28s;
  box-shadow: var(--lift-1);
}
/* A note that is not a tier must not sit in the flex row pretending to be one. */
.hm-tiers > .hm-tier-note { flex: 1 1 auto; max-width: none; }
.hm-tier:hover {
  transform: translate3d(0, -5px, 0);
  box-shadow: var(--lift-2);
}
.hm-tier-hi {
  border-color: var(--primary); transform: translate3d(0, -8px, 0);
  box-shadow: var(--lift-3);
}
.hm-tier-hi:hover { transform: translate3d(0, -12px, 0); }
@media (prefers-reduced-motion: reduce) {
  .hm-tier, .hm-tier-hi, .hm-tier:hover, .hm-tier-hi:hover { transform: none; }
}
.hm-amt {
  font-family: var(--font-display); font-size: 2.2rem; letter-spacing: -.032em;
  margin: .5rem 0 0; font-variant-numeric: tabular-nums;
}
.hm-per { font-size: .8rem; color: var(--text-faint); margin: 0; }
.hm-tier-desc { font-size: .87rem; color: var(--text-muted); margin: .7rem 0 0; }
.hm-tier ul {
  list-style: none; padding: 0; margin: 1.15rem 0 1.5rem; display: grid; gap: .44rem;
  font-size: .87rem; color: var(--text-muted);
}
.hm-tier li::before { content: "·"; color: var(--primary); font-weight: 700; margin-right: .5rem; }
.hm-tier .hm-btn { margin-top: auto; text-align: center; }
.hm-tier-note { color: var(--text-muted); font-size: .9rem; margin: 0; }
.hm-fineprint { margin-top: 1.3rem; font-size: .82rem; color: var(--text-faint); max-width: 62ch; }
.hm-center { text-align: center; }

/* ---------------------------------------------------------------- footer */
.hm-foot { padding: clamp(2.4rem, 5vw, 3.6rem) 0; background: var(--bg); }
.hm-fgrid {
  display: grid; grid-template-columns: 1.5fr 1fr 1fr 1fr; gap: 2rem;
  padding-bottom: 1.8rem; border-bottom: 1px solid var(--border);
}
@media (max-width: 720px) { .hm-fgrid { grid-template-columns: 1fr 1fr; gap: 1.4rem; } }
.hm-fdesc { font-size: .86rem; color: var(--text-muted); max-width: 34ch; margin: .7rem 0 0; }
.hm-fgrid h4 {
  font-size: .66rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--text-faint); font-weight: 700; margin: 0 0 .7rem;
}
.hm-fgrid a {
  display: block; font-size: .86rem; color: var(--text-muted); text-decoration: none;
  margin-bottom: .35rem;
}
.hm-fgrid a:hover { color: var(--primary); }
.hm-colophon {
  padding-top: 1.2rem; display: flex; justify-content: space-between; gap: 1rem;
  flex-wrap: wrap; font-size: .78rem; color: var(--text-faint);
}

/* ---------------------------------------------------------------- the sign-in modal */
/* The panel itself is auth_panel.js and brings its own styling from shared_styles.css. All
   this does is put it over the page and stop the page scrolling underneath it. */
.hm-modal-open { overflow: hidden; }
#hm-auth {
  position: fixed; inset: 0; z-index: 90; display: grid; place-items: center;
  padding: 1.2rem; overflow-y: auto;
  background: color-mix(in srgb, var(--text) 42%, transparent);
  backdrop-filter: blur(3px);
}
#hm-auth[hidden] { display: none; }
#hm-auth-mount { width: 100%; max-width: 420px; }
