/* Staging-site layer. Everything visual lives in the design system; this file only holds
   the two things inline React styles cannot express — hover state on the mega-menu links,
   and the breakpoints that let the design system's fixed layouts reflow. */

/* Hover firms the divider's pen and darkens its face a step — it never floods the stone with
   accent, which is the system's rule for hover: darken or firm, never lift or glow. */
.mega-link .dl-face, .mega-link .dl-ink { transition: fill var(--duration-fast) var(--ease-standard); }
.mega-link:hover .dl-ink { fill: var(--lapis-800); }
.mega-link:hover .dl-face { fill: var(--pumice-300); }
.mega-link:hover > span:first-of-type { color: var(--text-accent); }

/* LiveCostFlow (site/widget.jsx): a brief settle-in on each inputs/gate/sent step swap, so
   stepping through the cost calculator's own gate reads as a small in-place update rather than a
   page having just reloaded underneath it — Mike: "it looks and feels like you end up refreshing
   the whole page." Re-keyed per step so the animation restarts every swap, not just on mount. */
@keyframes lcf-fade-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.lcf-step { animation: lcf-fade-in .25s var(--ease-standard) both; }

/* The lockup and nav are clickable in the staging build. */
header a[aria-label] { cursor: pointer; }

/* Mike, 21 Sept: "when you click the run the numbers button... it also moves the login text with
   it." Button (design system, ds/_ds_bundle.js) reserves `marginRight: d` on its own root span to
   make room for its drawn 3D depth — d shrinks by up to 4px while pressed, the "compressed" look.
   That's correct for a button sitting among other normal-flow content, but the header's CTA sits
   in `.nav-actions`, a `margin-left: auto` group that's right-anchored against the header's own
   edge — any margin change ANYWHERE in that group shifts the whole cluster, including Login, the
   sibling before it. Can't fix this in the Button component itself (never fork the design
   system), so it's neutralized at the two call sites that put a Button next to other nav content:
   pinning the margin to its unpressed value (7px, this Button's own `md` depth) stops the
   fluctuation from ever reaching the flex layout, while the button's own inner artwork still
   visually compresses on press exactly as designed. */
.nav-actions > span, .mobile-menu-footer > span { margin-right: 7px !important; }

/* Input (design system) draws its focus ring on the native <input>, sitting outside the input's
   own border by default — SketchBox, the hand-drawn border around it, clips anything that
   crosses its own edge. Mike, wide-monitor review: focusing a Compare-page cost field showed
   "half" a focus ring, cut off along the bottom. Pulling the ring 2px inward keeps it inside the
   input's own box so SketchBox's clip never touches it — every Input and Select on the site
   shares this same structure, so the fix is global rather than one field at a time. */
input:focus-visible, select:focus-visible, textarea:focus-visible { outline-offset: -2px; }

/* Button (design system) sizes its drawn 3D face to whatever width its own <a>/<button> ends up
   at, via a ResizeObserver on that element itself — passing `style` only reaches Button's own
   outer wrapper span, not that inner element, so a plain `style={{width:'100%'}}` stretched the
   wrapper while the button inside stayed sized to its own text, leaving the label sitting outside
   the drawn box. The widget's own CTA and its collapsed trigger (site/widget.jsx) both want the
   drawn box itself to span the full width of the corner widget, so the inner element needs the
   override too — .sw-run-btn/.sw-trigger scope it to just these two buttons. */
.sw-run-btn > span > a {
  display: flex !important; width: 100%; box-sizing: border-box; justify-content: center;
}
/* The trigger's own text left-registered (its natural flex position) while the chevron's own
   `margin-left: auto` pinned it to the far right, so any slack width — the box briefly grows
   wider than the amount text needs, e.g. while the panel above is open on a long platform name —
   showed up as a gap in the middle instead of at either edge. Mike: that negative space should
   sit on the left, not split the label from the arrow. flex-end (not center, unlike the CTA
   above) pushes the whole label+arrow group to the right as one unit, so any slack collects
   before the text instead of between it and the chevron. */
.sw-trigger > span > button {
  display: flex !important; width: 100%; box-sizing: border-box; justify-content: flex-end;
}
/* Mike, 14 Sept: "there's some transparency built into there, and you can see the white or
   light gray box behind it... it only happens on the comparison page." Button (design system)
   draws 100% of its visible color from an absolutely-positioned SVG sized off a ResizeObserver
   reading of this same button — the button element itself is `background: transparent` in the
   component's own inline style, relying entirely on that SVG sitting behind... no, in front of it
   to ever show color at all. Every other Button on the site has a fixed label, so that SVG only
   resizes once, right after mount, and settles. This is the one Button whose own children re-render
   every second with a different number of digits (the live "$X spent on Y" ticker), which can
   change the button's own text width on any given tick — and for the single frame where the
   ResizeObserver hasn't yet caught up, the transparent button paints nothing, exposing whatever
   is actually scrolled underneath this fixed-position corner widget. Invisible over a dark
   section (home page's own dark footer) and glaring over a light one (the Compare pages' own
   light card grid) — which is exactly the inconsistency Mike saw. Giving the button element
   itself a solid, static fallback in the same front/hover tones the SVG already draws (SKINS.
   primary.front/HOVER.primary.front in ds/_ds_bundle.js) means it always shows solid color
   even mid-resize, and the :hover rule keeps the darken-on-hover feel without depending on the
   SVG's own (now-obscured) hover-state fill. */
.sw-trigger > span > button {
  background: var(--lapis-600) !important; border-radius: 4px;
}
.sw-trigger > span > button:hover {
  background: var(--lapis-700) !important;
}

/* --container-max is a design-system token the reference kit never spends (bumped 1200->1440px,
   site/apply_ds_changes.py — Mike, on a 32" monitor, felt too narrow). Above the width where the
   gutter alone stops holding the measure — container-max + two gutters, 1440 + 2×56 = 1552px —
   the gutter grows into it so the column of text keeps the same length past that point instead
   of continuing to widen with the viewport.

   `section` and `footer` used to be matched as direct children of #root's own wrapper div
   (#root > div > section / > footer). That broke twice over: `.rv-wrap` (site/review.jsx) wraps
   every reviewed section in its own div, so with review mode on — the mode Mike actually reviews
   in — no section matched the selector at all and every block rendered edge to edge, capped only
   by the 56px gutter; and SiteFooter has always shipped inside its own `.site-footer-wrap`, so
   the footer never matched even with review mode off. Header isn't wrapped either way, so its
   selector stays as it was. Matching `section`/`footer` anywhere under #root, instead of only at
   one exact depth, survives whichever wrapper is or isn't between them and the root. */
@media (min-width: 1552px) {
  #root section,
  #root footer,
  #root > div > div > header,
  .mega-panel,
  .rv-detail {
    padding-left: calc((100% - var(--container-max)) / 2) !important;
    padding-right: calc((100% - var(--container-max)) / 2) !important;
  }
  /* Mike: the sticky-note tabs (site/review.jsx) sit at a fixed `var(--gutter)` inset from
     .rv-wrap, which is full-bleed — on a wide monitor that left them well outside the section's
     own now-capped content column, reading as attached to the page edge instead of the block
     they annotate. Past this breakpoint the tab's inset grows the same way the section's own
     padding just did, so it lines up with the column it's labeling.

     Real bug from the first attempt at this, caught by Mike: these tabs never set their own
     width, and setting BOTH `left` and `right` (!important) on an absolutely positioned element
     with width:auto doesn't just move it — per the CSS spec that combination makes the browser
     *compute* width to fill the entire gap between the two edges, which is exactly why a small
     pill suddenly spanned the whole section. `left` alone repositions it; the width stays
     content-sized because `right` is never touched. `.rv-tab-illustration` (the illustration
     notes, positioned in-flow after a drawing, not pinned to a block's corner) and
     `.rv-tab-inline` (the header's own tab, sitting in the nav bar's own flex row) are excluded
     here since they're relatively/statically positioned, not corner-pinned, and `left` on a
     relatively positioned element shifts it from its own in-flow position rather than from the
     section's edge, which is exactly what put the illustration notes in the wrong place. */
  .rv-tab-resolved:not(.rv-tab-inline):not(.rv-tab-illustration) {
    left: calc((100% - var(--container-max)) / 2 + var(--gutter)) !important;
  }
}

@media (max-width: 1040px) {
  .split { grid-template-columns: 1fr !important; }
}
/* A grid item's default min-width is auto, not 0 — it refuses to shrink below its own content's
   intrinsic width. Harmless when a .split column is wide enough to hold that content, but once
   the column collapses to 1fr at a phone width, a long StatRow value or Card paragraph can still
   force the track wider than .split's own box, overflowing the page. Same bug, same fix, as the
   StatRow ol rule below — just one layer up. */
.split > * { min-width: 0; }

/* ------------------------------------------------------------------- mobile nav
   Mike: the header used to just let the inline nav wrap onto extra lines below 980px — "poorly
   designed." A hamburger (site/nav.jsx) replaces the inline nav, Login and CTA outright at the
   same width instead of reflowing them, with a hand-drawn three-line icon that turns into an X. */
/* header lays its children out on align-items: baseline — right for the logo and nav labels,
   which share a text baseline, but a button has none, so the flex box fell back to aligning its
   bottom edge instead, sitting low against everything beside it. align-self overrides just this
   one item back to the row's own vertical center. */
.nav-hamburger { display: none; align-self: center; background: none; border: 0; padding: 4px; margin-left: auto; cursor: pointer; }
@media (max-width: 900px) {
  /* Both carry an inline display:flex (React) — a non-!important stylesheet rule never beats
     that regardless of selector specificity, so the override needs it here. */
  header nav.nav-links, header .nav-actions { display: none !important; }
  .nav-hamburger { display: block; }
  /* The header's own review tab ("Section AA") is the only .rv-tab-inline on the site — with
     the inline nav gone, it was the one thing left pushing the hamburger button off the edge
     of the screen. Reachable from Section index regardless. */
  .rv-tab-inline { display: none !important; }
}

.mobile-menu {
  position: relative; z-index: 20; background: var(--surface-card);
  border-top: 1.5px solid var(--stone-400);
  box-shadow: 0 14px 24px -14px rgba(0,0,0,.3);
  padding: 6px var(--gutter) 22px;
  display: flex; flex-direction: column;
}
.mobile-menu-row {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%; text-align: left; background: none; border: 0; cursor: pointer;
  padding: 15px 0; font: var(--weight-bold) 16px/1 var(--font-body); color: var(--text-primary);
  border-bottom: 1px solid var(--stone-200, rgba(0,0,0,.08));
}
.mobile-menu-chevron { color: var(--text-muted); font-weight: 400; font-size: 20px; line-height: 1; }
.mobile-menu-sublist { display: flex; flex-direction: column; padding: 2px 0 10px 14px; }
.mobile-menu-sublink { padding: 11px 0; font: var(--type-body); color: var(--text-secondary); border-bottom: 0; }
/* Login and the CTA, side by side — the last nav row's own bottom border is the only divider
   between the link list and this row, not a second one stacked on top of it. Mike: the gap
   above the button read tighter than the gap below it (18px against the menu's own 22px bottom
   padding, plus the button's own height) — past 32px it clearly reads as more, not less.
   justify-content was space-between, which spreads Login and the button to opposite edges of
   the menu — on a phone-width menu that put real distance between them. Desktop puts them
   adjacent, both against the bar's right edge (site/nav.jsx's own .nav-actions is
   margin-left: auto); flex-end matches that here, Login sitting directly left of the CTA. */
.mobile-menu-footer { display: flex; align-items: center; justify-content: flex-end; gap: 16px; padding-top: 32px; }

@media (max-width: 900px) {
  :root { --gutter: 32px; }
  h1 { font: var(--type-display-2) !important; letter-spacing: var(--tracking-display); }
}

@media (max-width: 620px) {
  :root { --gutter: 22px; }
  h1 { font: var(--type-display-3) !important; letter-spacing: var(--tracking-display); }
}

/* Footer links are wired by label in nav.jsx; they carry href="#" from the design system. */
footer a { cursor: pointer; }
footer svg[aria-label], footer svg { cursor: pointer; }

/* ------------------------------------------------------------------ review layer
   Citable section tabs for the page-by-page review. Deliberately NOT brand UI: yellow on a site
   that never uses yellow, slightly askew, so they read as stuck on rather than designed in. The
   tab sits in the top padding of each block and covers nothing. See site/review.jsx.

   Mike, 17 Sept, final pass: "turn all the sticky notes into yellow ones that don't show any
   additional info." Every other state this layer used to have — the plain clickable yellow tab
   with a "verified"/"N to confirm" flag, red ("N to decide"), orange (illustration asks), and the
   four-column open note they all expanded into — is gone along with the components that rendered
   them (Tab and IllustrationNote now always render the plain, inert `.rv-tab-resolved` label
   below). Only that inert style, the illustration positioning it borrows, and the toolbar remain. */
.rv-tab-inline { position: static; margin-left: auto; align-self: center; transform: rotate(-1deg); }

/* Mike: moved off the bottom-right corner to make room for the live savings widget
   (site/widget.jsx) that lives there now. */
.rv-bar {
  position: fixed; left: 16px; bottom: 16px; z-index: 70;
  display: flex; align-items: center; gap: 12px; padding: 8px 10px 8px 12px;
  background: #FFF0A0; color: #2B2300; box-shadow: 0 10px 24px -10px rgba(0,0,0,.5);
  font: 400 12.5px/1 var(--font-body); transform: rotate(-0.6deg);
}
.rv-bar .rv-pill { font-weight: 700; letter-spacing: 0.02em; }
.rv-bar .rv-page b { font: var(--weight-bold) 15px/1 var(--font-display); margin-right: 4px; }
.rv-bar a { color: #2B2300; border-bottom: 1px solid rgba(43,35,0,.5); }
.rv-bar button, .rv-bar-off {
  font: 700 12px/1 var(--font-body); padding: 6px 10px; border: 1.5px solid #2B2300;
  background: transparent; color: #2B2300; cursor: pointer;
}
.rv-bar-off { position: fixed; left: 16px; bottom: 16px; z-index: 70; background: #FFF0A0; opacity: .9; }
/* Mike: the live savings widget (site/widget.jsx) now owns the bottom row on a phone-width
   screen — its collapsed pill runs close to full width there, same as .rv-bar itself once it
   carries "Review mode / Section index / Hide", so bottom-left and bottom-right collide well
   before either reaches the opposite corner. The review bar is an internal tool; moving it to
   the top corner below the width where that collision starts costs reviewers nothing and leaves
   the bottom row to the one thing every visitor sees. */
@media (max-width: 700px) {
  .rv-bar, .rv-bar-off { bottom: auto; top: 74px; }
}

/* The illustration note sits beside the drawing itself rather than in the block's top padding —
   there is no fixed slot for it, so it is positioned inline, right after the drawing. */
.rv-illustration-wrap { position: relative; }
.rv-tab-illustration { position: relative; margin-top: 10px; transform: rotate(-1deg); }

/* The one tab style left: a plain, non-interactive label — the section (or illustration) code
   stays citable ("Section BB," "Illustration BEV") without offering a note there's nothing left
   to read. No cursor, no hover, no flag, no color other than this one yellow. */
.rv-tab-resolved {
  position: absolute; z-index: 20; display: inline-flex; align-items: center;
  padding: 6px 12px 6px 10px; background: #FFF0A0; color: #2B2300; opacity: .75;
  box-shadow: 0 6px 14px -8px rgba(0,0,0,.5), 0 1px 0 rgba(0,0,0,.10);
  transform: rotate(-1.2deg); font: 400 11px/1 var(--font-body); white-space: nowrap;
}
.rv-tab-resolved b { font: var(--weight-bold) 15px/1 var(--font-display); letter-spacing: -0.01em; }
.rv-tab-resolved.rv-tab-inline { position: static; margin-left: auto; align-self: center; transform: rotate(-1deg); }

/* -------------------------------------------------------------- responsive grids
   Mike, v2 review: flex-wrap and auto-fit both reflow by whatever fits the available width,
   which gave the hero badges 3-then-1 on a wide screen and let the leverage cards stretch to 4
   columns instead of holding their 3x2 grid — and neither had been checked at a phone width at
   all. Both grids now hold a fixed column count down to one real breakpoint, then go to 1. */
/* Mike, 14 Sept, round two: justify-items:start (his first note: "too much negative space...
   they should shrink down horizontally") let each pill hug its own text, but that meant four
   DIFFERENT widths with a gap wherever a shorter one sat next to the grid's own leftover column
   space — "they should all be a consistent width... this gigantic gap." An explicit shared width
   on Badge's own root span (not just its text), sized to comfortably fit the longest of the four
   ("Managed without opening a single inbound port") on one line, made all four match — but with
   the columns still sized `1fr` (equal shares of the whole hero column), each 360px pill sat
   inside a MUCH wider track, and that unused track space read as extra gap on top of the real
   one. Round three: `max-content` columns size the track to the pill's own fixed width exactly,
   so the only space between them is the gap value itself — 12px, matching the CTA buttons' own
   gap right above this row, per Mike: "about the same distance as the two calls to action." */
.hero-badges { display: grid; grid-template-columns: repeat(2, max-content); gap: 12px; justify-items: start; }
.hero-badges > span { width: 360px; box-sizing: border-box; }
.leverage-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
/* Mike, 16 Sept review: Platform overview's own four-card "table of contents" (site/pages.jsx,
   PlatformList) used the shared three-column grid above, which wraps 4 cards as 3-then-1 — "it's
   supposed to be two and two." A dedicated two-column class rather than an inline style override,
   so the same @media collapse to one column at narrow widths still applies (an inline
   gridTemplateColumns would out-specificity that media query and stay two-up on a phone). */
.leverage-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
/* The Basalt-versus-competitor result pair on each Compare page's cost estimate (site/pages.jsx,
   CostCompare) — two cards side by side above 620px, same breakpoint as the grids above. */
.cost-compare-result { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
@media (max-width: 620px) {
  .hero-badges { grid-template-columns: 1fr; }
  /* The fixed 360px pill width (above) is sized for a 2-up desktop grid — at 1-up on a narrow
     phone it can run past the gutter with no room to spare. Full width of the single column
     instead, same as it was before this width was ever a fixed number. */
  .hero-badges > span { width: 100%; }
  .leverage-grid { grid-template-columns: 1fr; }
  .leverage-grid-2 { grid-template-columns: 1fr; }
  .cost-compare-result { grid-template-columns: 1fr; }
}
/* Badge (design system) hardcodes white-space: nowrap on its own label — fine for a short pill,
   not for a full claim sentence at 2-up or 1-up width on a narrow screen. Only overridden inside
   the hero badge grid, not the component itself. */
.hero-badges span { white-space: normal !important; }

/* SiteFooter (design system) hardcodes a 5-column grid (`1.3fr repeat(4,1fr)`) with no
   responsive rule of its own — real overflow at a phone width, not just a squeeze. Targeted by
   the inline style itself, since the grid div carries no class to hook a media query onto
   without forking the component. */
@media (max-width: 900px) {
  .site-footer-wrap footer > div[style*="grid-template-columns"] { grid-template-columns: 1fr 1fr !important; }
}
@media (max-width: 620px) {
  .site-footer-wrap footer > div[style*="grid-template-columns"] { grid-template-columns: 1fr !important; }
}

/* StatRow (design system) doesn't set its own grid-template-columns, so the browser sizes the
   implicit column to the widest un-wrapping content — a stat's `value` text, held to one line by
   its own white-space: nowrap. A long value (e.g. compare pages) pushes that column past the
   row's own box instead of wrapping inside it, at any width. Clamping the track to the row's own
   width lets the wrap rules already inside each row do their job. `ol` disambiguates it from
   SiteFooter's link lists, which use the same list-style/display:grid pair on a `ul`. */
ol[style*="list-style: none"] { grid-template-columns: minmax(0, 1fr) !important; }

/* Design/dev director review, 21 Sept: the fixed-position savings widget (site/widget.jsx,
   SavingsWidget) had no mobile handling — at 375px its expanded panel's 320px maxWidth left it
   covering nearly the entire viewport, and its collapsed trigger sat on top of in-flow CTAs and
   body copy on every page (it mounts unconditionally, site-wide, via SiteFoot). Same 620px
   breakpoint as every other mobile fix on the site. Capping the panel's own height (not the
   window's) keeps the header — and the ✕ added alongside this rule — always reachable, and
   shrinking the collapsed trigger's padding/font reduces how much of whatever's underneath it
   actually gets covered, though a fixed-position element unavoidably covers something at this
   width; the ✕ is the real fix for "can't get back to the page." */
@media (max-width: 620px) {
  .sw-panel { max-height: 70vh; overflow-y: auto; }
  .sw-trigger > span > button { padding: 8px 12px !important; font-size: 13px !important; }
}
