:root {
  --bg: #121212;
  --surface: #1c1c1c;
  --surface-2: #232323;
  --border: rgba(255, 255, 255, 0.08);
  --border-strong: rgba(255, 255, 255, 0.14);
  --accent: #3fae5c;
  --accent-bright: #5fd47f;
  --text: #eaeaea;
  --text-dim: #8f8f8f;
  --nav-text: #9a9a9a;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  /* Mobile Safari/Chrome shade the tapped element with a translucent grey
     box by default (visible as a "black frame" on transparent buttons like
     .sync-btn, and as a stray highlight on nav tabs). Every custom tap/hover
     state below is deliberate, so the built-in one is turned off globally
     rather than patched per element. */
  -webkit-tap-highlight-color: transparent;
}

html, body {
  background: var(--bg);
  color: var(--text);
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  /* Two faint green glows in opposite corners of the page. The top-left one
     is anchored at a fixed px offset (0px, 52px) — 52px is the navbar's
     height — instead of the literal corner, otherwise its brightest core
     sits exactly behind the opaque navbar and only a thin sliver peeks out
     underneath it. The bottom-right one has nothing opaque covering it, so
     it can stay at the literal corner (100% 100%). Reads as ambient light
     framing the page rather than a spotlight. On the homepage it sits
     behind the opaque .hero section and never shows. */
  background-image:
    radial-gradient(ellipse 900px 680px at 0px 52px, rgba(95, 212, 127, 0.26), transparent 65%),
    radial-gradient(ellipse 900px 680px at 100% 100%, rgba(95, 212, 127, 0.18), transparent 65%);
  background-repeat: no-repeat, no-repeat;
  background-size: auto, auto;
}

/* Enlarged logo watermark, bottom-right, fixed to the viewport so it's
   always present without depending on page length. Non-interactive.
   z-index: 0 (NOT -1) — a negative z-index here renders BEHIND body's own
   background color (body's background paints later in the stacking order
   than a negative-z-index child), which hid it completely. z-index 0 means
   it technically paints above in-flow content instead, but at 13% opacity
   with pointer-events off, that's invisible in practice and never blocks
   clicks. */
.page-watermark {
  position: fixed;
  bottom: -110px;
  right: -110px;
  width: 520px;
  height: 520px;
  opacity: 0.24;
  pointer-events: none;
  user-select: none;
  z-index: 0;
}

.mono-label {
  font-family: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
}

a {
  color: inherit;
  text-decoration: none;
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------- Navbar ---------- */
.navbar {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 0 24px;
  height: 52px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 100;
}

.nav-links {
  flex: 1;
  display: flex;
  align-items: stretch;
  align-self: stretch;
  list-style: none;
}

.nav-links li {
  flex: 1;
  display: flex;
}

.nav-links li:not(:last-child) {
  border-right: 1px solid var(--border);
}

.nav-links a {
  position: relative;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15.5px;
  font-weight: 600;
  letter-spacing: 0.2px;
  color: var(--nav-text);
  overflow: hidden;
  transition: color 0.2s ease, background 0.15s ease;
}

.nav-links a span {
  position: relative;
}

.nav-links a.active,
.nav-links a:focus-visible {
  color: var(--accent-bright);
}

/* Nav tabs react as a whole rectangle, not a cursor-tracked glow — the
   glow/spotlight effect is reserved for content-page elements (panels,
   tool cards, auth card). The :hover variant is gated to devices with a
   real pointer: touch simulates :hover on tap but has no mouse-out to end
   it, so on a phone a tab could stay lit green after you'd moved on — this
   keeps hover feedback for mouse users without that stuck-highlight glitch
   on touch. :focus-visible/.active (below) still work everywhere. */
@media (hover: hover) and (pointer: fine) {
  .nav-links a:hover {
    color: var(--accent-bright);
    background: rgba(63, 174, 92, 0.12);
  }
}

.nav-links a:focus-visible {
  background: rgba(63, 174, 92, 0.12);
}

.nav-links a.active {
  background: rgba(63, 174, 92, 0.16);
}

.nav-right {
  display: flex;
  align-items: center;
  gap: 4px;
}

.icon-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 7px;
  color: var(--nav-text);
  transition: color 0.18s ease, background 0.18s ease;
}

.icon-btn svg {
  width: 17px;
  height: 17px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.icon-btn:hover,
.icon-btn:focus-visible {
  color: var(--accent-bright);
  background: rgba(63, 174, 92, 0.1);
}

.profile-menu {
  position: relative;
  display: flex;
}

.profile-btn-open {
  color: var(--accent-bright);
  background: rgba(63, 174, 92, 0.1);
}

.profile-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 190px;
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  padding: 6px;
  box-shadow: 0 14px 32px rgba(0, 0, 0, 0.4);
  z-index: 200;
}

.profile-dropdown[hidden] { display: none; }

.profile-dropdown-email {
  display: block;
  padding: 8px 10px 6px;
  font-size: 12px;
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border-bottom: 1px solid var(--border);
  margin-bottom: 4px;
}

.profile-dropdown-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 9px 10px;
  border-radius: 6px;
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  background: none;
  border: none;
  cursor: pointer;
  transition: color 0.15s ease, background 0.15s ease;
}

.profile-dropdown-item:hover,
.profile-dropdown-item:focus-visible {
  color: #e08585;
  background: rgba(176, 64, 64, 0.12);
  outline: none;
}

.logo-link {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  position: relative;
  flex-shrink: 0;
}

.logo-link img {
  width: 100%;
  height: 100%;
  display: block;
  position: relative;
  z-index: 1;
  transition: filter 0.2s ease;
}

.logo-link::before {
  content: "";
  position: absolute;
  /* Kept small enough (with the 1.06 breathe scale below) that it never
     pokes past the 52px navbar — the logo-link is 44px, centered in the
     navbar with only 4px of margin above/below. */
  inset: -2px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(95, 212, 127, 0.55) 0%, rgba(95, 212, 127, 0) 70%);
  opacity: 0;
  z-index: 0;
}

.logo-link:hover::before,
.logo-link:focus-visible::before {
  animation: zoreBreathe 1.7s ease-in-out infinite;
}

.logo-link:hover img,
.logo-link:focus-visible img {
  filter: drop-shadow(0 0 6px rgba(95, 212, 127, 0.9));
}

/* Ring that expands outward from the center into a full circle on hover —
   replaces the ring that used to be baked into the logo image itself
   (that raster ring aliased unevenly at small sizes; this is drawn live). */
.logo-link::after {
  content: "";
  position: absolute;
  /* Same inset cap as ::before — at scale(1) this stays inside the
     52px navbar instead of poking past its top/bottom edge. */
  inset: -2px;
  border-radius: 50%;
  border: 1.5px solid rgba(95, 212, 127, 0.85);
  opacity: 0;
  transform: scale(0.25);
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.3s ease;
  z-index: 0;
  pointer-events: none;
}

.logo-link:hover::after,
.logo-link:focus-visible::after {
  opacity: 1;
  transform: scale(1);
}

@keyframes zoreBreathe {
  0%   { opacity: 0.25; transform: scale(0.96); }
  50%  { opacity: 1;    transform: scale(1.06); }
  100% { opacity: 0.25; transform: scale(0.96); }
}

@media (prefers-reduced-motion: reduce) {
  .logo-link:hover::before,
  .logo-link:focus-visible::before {
    animation: none;
    opacity: 0.6;
  }
  .logo-link:hover::after,
  .logo-link:focus-visible::after {
    transition: opacity 0.3s ease;
    transform: scale(1);
  }
}

/* ---------- Hero (home page) ---------- */
.hero {
  min-height: 100vh;
  padding: 100px 24px;
  background: linear-gradient(180deg, #050505 0%, #0d1c10 40%, #1f5c30 78%, #2f8a42 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.hero .eyebrow {
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--accent-bright);
  margin-bottom: 16px;
}

.hero h1 {
  font-family: "PT Serif", Georgia, "Times New Roman", serif;
  font-size: 104px;
  font-weight: 700;
  letter-spacing: -1px;
  line-height: 1;
  margin-bottom: 10px;
  text-wrap: balance;
  animation: heroLineIn 0.6s ease-out both;
}

.hero .tagline {
  font-size: 26px;
  font-weight: 600;
  color: var(--accent-bright);
  margin-bottom: 20px;
  animation: heroLineIn 0.6s ease-out 0.22s both;
}

.hero p {
  font-size: 16px;
  color: rgba(234, 234, 234, 0.75);
  max-width: 480px;
  line-height: 1.6;
  margin-bottom: 28px;
  animation: heroLineIn 0.6s ease-out 0.4s both;
}

@keyframes heroLineIn {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .hero h1,
  .hero .tagline,
  .hero p,
  .sync-btn {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

/* ---------- Sync Now button ---------- */
.sync-btn {
  position: relative;
  width: 156px;
  height: 156px;
  margin-top: 12px;
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: heroLineIn 0.6s ease-out 0.55s both;
}

.sync-ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.ring-fill {
  /* Hover-driven charge: empty by default, fills to a full circle while
     hovered/focused, and reverses back to empty once you leave — a plain
     transition (not a keyframe animation) so it can hold or reverse from
     wherever it currently is, instead of always restarting from 0%. */
  stroke-dashoffset: 100;
  transition: stroke-dashoffset 1s ease-out, filter 0.3s ease;
}

.sync-core {
  position: relative;
  z-index: 1;
  width: 122px;
  height: 122px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 32%, #163420 0%, #0b1710 72%);
  border: 1px solid var(--border-strong);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: transform 0.25s ease, box-shadow 0.25s ease, background 0.25s ease;
}

.sync-core svg {
  width: 22px;
  height: 22px;
  stroke: var(--accent-bright);
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.sync-core span {
  font-family: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text);
}

@media (hover: hover) and (pointer: fine) {
  .sync-btn:hover .sync-core {
    transform: scale(1.06);
    box-shadow: 0 0 34px rgba(95, 212, 127, 0.45), inset 0 0 20px rgba(95, 212, 127, 0.18);
    background: radial-gradient(circle at 50% 32%, #1e4a2a 0%, #0b1710 76%);
  }

  .sync-btn:hover .ring-fill {
    stroke-dashoffset: 0;
    filter: drop-shadow(0 0 6px rgba(95, 212, 127, 0.85));
  }
}

.sync-btn:focus-visible .sync-core,
.sync-btn.is-charged .sync-core {
  transform: scale(1.06);
  box-shadow: 0 0 34px rgba(95, 212, 127, 0.45), inset 0 0 20px rgba(95, 212, 127, 0.18);
  background: radial-gradient(circle at 50% 32%, #1e4a2a 0%, #0b1710 76%);
}

.sync-btn:focus-visible .ring-fill,
.sync-btn.is-charged .ring-fill {
  stroke-dashoffset: 0;
  filter: drop-shadow(0 0 6px rgba(95, 212, 127, 0.85));
}

@media (prefers-reduced-motion: reduce) {
  .ring-fill {
    transition: none;
  }
  .sync-btn:hover .sync-core,
  .sync-btn:focus-visible .sync-core,
  .sync-btn.is-charged .sync-core {
    transform: none;
  }
}

.gradient-text {
  background: linear-gradient(90deg, #eafff0 0%, var(--accent-bright) 45%, var(--accent) 100%);
  background-size: 200% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: shimmerText 7s ease-in-out infinite alternate;
}

@keyframes shimmerText {
  from { background-position: 0% 50%; }
  to   { background-position: 100% 50%; }
}

@media (prefers-reduced-motion: reduce) {
  .gradient-text { animation: none; background-position: 40% 50%; }
}

.btn-primary {
  display: inline-block;
  background: var(--accent);
  color: #06120a;
  font-weight: 700;
  font-size: 14px;
  padding: 13px 28px;
  border-radius: 8px;
  transition: transform 0.15s ease, background 0.15s ease;
}

.btn-primary:hover {
  background: var(--accent-bright);
  transform: translateY(-1px);
}

.status-pill {
  margin-top: 24px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: rgba(234, 234, 234, 0.6);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  padding: 6px 14px;
  border-radius: 999px;
}

.status-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #555;
}

.status-dot.online {
  background: var(--accent-bright);
  box-shadow: 0 0 8px var(--accent-bright);
}

.status-dot.offline {
  background: #b04040;
  box-shadow: none;
}

/* ---------- Inner pages ---------- */
.page-header {
  padding: 64px 32px 8px;
  /* Wider than .hero's readable-text widths on purpose — this wraps the
     whole page body, and 1080px left huge dead gutters on a real desktop
     monitor (1920px+). 1320px is still well short of "wall-to-wall" but
     visibly narrows the empty sides. Doesn't touch mobile: viewports below
     this are already narrower than the old 1080px cap, so this only ever
     binds on screens wider than 1080px. */
  max-width: 1320px;
  margin: 0 auto;
}

.page-header .tag {
  font-family: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--accent-bright);
  margin-bottom: 8px;
}

.page-header h2 {
  font-size: 30px;
  font-weight: 700;
}

.page-header p {
  color: var(--text-dim);
  margin-top: 8px;
  max-width: 540px;
  font-size: 14.5px;
  line-height: 1.6;
}

.block {
  padding: 32px 32px 80px;
  /* Matches .page-header's 1320px — same reasoning, same file/section. */
  max-width: 1320px;
  margin: 0 auto;
}

.tool-grid {
  display: grid;
  /* min(440px, 100%) instead of a bare 440px: on desktop it packs 2+ cards
     per row (the actual request — Converter/Tax Calculator no longer force
     a full-width row each, see .tax-card/.projector-card/.converter-card
     below); on a narrow phone screen the min clamps to 100% so it still
     collapses to one column instead of overflowing. */
  grid-template-columns: repeat(auto-fit, minmax(min(440px, 100%), 1fr));
  /* Grid's default is align-items:stretch — every card in a row gets
     forced to match the row's TALLEST card, which is why Tax Calculator
     (a short form) was inheriting Converter's height and sitting on top of
     a slab of empty space. start = each card is only as tall as its own
     content. */
  align-items: start;
  gap: 16px;
}

.tool-card {
  background: var(--surface);
  border: 1px solid rgba(95, 212, 127, 0.35);
  border-radius: 10px;
  padding: 22px;
  min-height: 120px;
  color: var(--text-dim);
  font-size: 13.5px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  border-style: dashed;
  position: relative;
  overflow: hidden;
}

/* Cursor-tracked hover glow, same technique as .panel::after (see JS
   attachSpotlight, which sets --mx/--my on pointermove). Uses ::before
   because ::after is already the laser border ring on this element. */
.tool-card::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(260px circle at var(--mx, 50%) var(--my, 50%), rgba(95, 212, 127, 0.12), transparent 70%);
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
}

.tool-card:hover::before {
  opacity: 1;
}

/* ---------- Currency converter tool ---------- */
.converter-card {
  border-style: solid;
  border-color: rgba(95, 212, 127, 0.45);
  display: block;
  text-align: left;
  padding: 22px 24px;
  min-height: 0;
  /* The side-by-side row layout below needs the CARD to be wide enough,
     which depends on how many columns .tool-grid gives it — not on the
     viewport. A container query (keyed off this card's own rendered
     width) reflows it correctly whether it's full-width alone or sharing
     a row with Tax Calculator, instead of a @media breakpoint that only
     ever knew about the viewport and got it wrong once the card could be
     narrower than the screen. */
  container-type: inline-size;
}

/* Traveling light around the WHOLE border (not just one edge): a
   conic-gradient masked down to a thin ring exactly on the border, rotating
   clockwise, continuously, one direction, no reset. Only the gradient's
   angle rotates (via the animated @property) — the element itself never
   transforms — so the ring stays aligned to the card's corners even though
   the cards aren't square. */
@property --border-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

.tool-card::after,
.converter-card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 2px;
  background: conic-gradient(
    from var(--border-angle),
    transparent 0deg,
    transparent 260deg,
    var(--accent-bright) 300deg,
    #eafff0 320deg,
    var(--accent-bright) 340deg,
    transparent 360deg
  );
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: exclude;
  animation: laserOrbit 4.5s linear infinite;
  pointer-events: none;
}

@keyframes laserOrbit {
  to { --border-angle: 360deg; }
}

.tool-label {
  font-family: "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 24px;
  font-weight: 700;
  color: var(--accent-bright);
  margin-bottom: 20px;
}

.converter-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
}

.converter-side {
  flex: 1 1 220px;
  max-width: 320px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.converter-side:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(95, 212, 127, 0.15);
}

.converter-side.result-side {
  background: rgba(63, 174, 92, 0.08);
  border-color: rgba(95, 212, 127, 0.4);
}

.converter-side.result-side:focus-within {
  border-color: var(--accent-bright);
  box-shadow: 0 0 0 3px rgba(95, 212, 127, 0.22);
}

.side-amount {
  background: none;
  border: none;
  padding: 0;
  width: 100%;
  text-align: center;
  font-family: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 26px;
  font-weight: 700;
  color: var(--text);
}

.side-amount:focus { outline: none; }

.converter-side.result-side .side-amount {
  color: var(--accent-bright);
}

.side-amount::placeholder {
  color: var(--text-dim);
}

.side-currency {
  background: none;
  border: none;
  border-top: 1px solid var(--border);
  padding: 8px 0 0;
  width: 100%;
  text-align: center;
  text-align-last: center;
  font-family: inherit;
  font-size: 16px;
  font-weight: 600;
  color: var(--text);
}

.side-currency:focus {
  outline: none;
}

.converter-side.result-side .side-currency {
  color: var(--accent-bright);
  border-top-color: rgba(95, 212, 127, 0.3);
}

/* Native dropdown popup: force black bg / white text on both sides so the
   list is always legible, regardless of the closed-select color above. */
.side-currency option {
  background: var(--bg);
  color: var(--text);
}

.swap-btn {
  width: 38px;
  height: 38px;
  min-width: 38px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--accent-bright);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform 0.25s ease, border-color 0.15s ease;
}

.swap-btn svg {
  width: 16px;
  height: 16px;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.swap-btn:hover,
.swap-btn:focus-visible {
  border-color: var(--accent);
  transform: rotate(180deg);
}

.convert-submit-row {
  margin-top: 20px;
  display: flex;
  justify-content: center;
}

.convert-submit {
  border: none;
  cursor: pointer;
  font-family: inherit;
  min-width: 160px;
}

.convert-submit:disabled {
  opacity: 0.6;
  cursor: default;
  transform: none;
}

.converter-meta {
  display: none;
  margin-top: 16px;
  text-align: center;
  font-family: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 12px;
  color: var(--text-dim);
}

.converter-meta.is-visible { display: block; }

.converter-error {
  display: none;
  margin-top: 14px;
  text-align: center;
  font-size: 13px;
  color: #e08585;
}

.converter-error.is-visible { display: block; }

/* ---------- Currency converter: single/multiple mode toggle ---------- */
.converter-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 20px;
}

.converter-head .tool-label {
  margin-bottom: 0;
}

.mode-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
}

.mode-toggle-label {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-dim);
  transition: color 0.15s ease;
}

.mode-toggle-label.is-active {
  color: var(--accent-bright);
}

.mode-switch {
  position: relative;
  width: 42px;
  height: 24px;
  min-width: 42px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  cursor: pointer;
  padding: 0;
  transition: background 0.2s ease, border-color 0.2s ease;
}

.mode-switch[aria-checked="true"] {
  background: var(--accent);
  border-color: var(--accent);
}

.mode-switch-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--text);
  transition: transform 0.2s ease, background 0.2s ease;
}

.mode-switch[aria-checked="true"] .mode-switch-knob {
  transform: translateX(18px);
  background: #06120a;
}

.converter-mode[hidden] { display: none; }

/* ---------- Currency converter: multiple-currency mode ---------- */
.multi-rows {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 14px;
}

.multi-row {
  display: flex;
  align-items: center;
  gap: 12px;
  /* Flex items refuse to shrink past their own content's natural width by
     default (min-width:auto) — .multi-row-box's <select> (long currency
     names, white-space:nowrap) was hitting that floor and forcing this row
     wider than the card, which is what pushed the remove button onto its
     own line and left the ragged gaps below ~640px. min-width:0 lets it
     actually shrink to the available space instead. */
  min-width: 0;
}

/* Amount left, currency right. .side-amount / .side-currency are shared
   with single mode (which stacks them instead), so the divider/sizing is
   overridden below, scoped to this box, for the horizontal arrangement. */
.multi-row-box {
  flex: 1 1 auto;
  min-width: 0;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px 18px;
  display: flex;
  align-items: center;
  gap: 14px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.multi-row-box:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(95, 212, 127, 0.15);
}

.multi-row-box .side-amount {
  /* 50/50 split (not auto-width) so the divider sits at the box's actual
     center, and — since every row's box is the same overall width (see
     .remove-row-btn-spacer below) — lands at the same x on every row too,
     regardless of how long the selected currency's name is. min-width:0
     overrides the flex default of "never shrink past my content" — without
     it this pair could force .multi-row-box (and the row above it) wider
     than the card on a narrow screen. */
  flex: 1 1 50%;
  width: auto;
  min-width: 0;
}

.multi-row-box .side-currency {
  flex: 1 1 50%;
  width: auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  border-top: none;
  border-left: 1px solid var(--border);
  padding: 0 0 0 14px;
}

/* Result row reuses this same box, just tinted green like single mode's
   result side, so the "answer" reads as the same kind of component as the
   rows that produced it. */
.multi-row-box.is-result {
  background: rgba(63, 174, 92, 0.08);
  border-color: rgba(95, 212, 127, 0.4);
}

.multi-row-box.is-result:focus-within {
  border-color: var(--accent-bright);
  box-shadow: 0 0 0 3px rgba(95, 212, 127, 0.22);
}

.multi-row-box.is-result .side-amount {
  color: var(--accent-bright);
}

.multi-row-box.is-result .side-currency {
  color: var(--accent-bright);
  border-left-color: rgba(95, 212, 127, 0.3);
}

/* .multi-row-amount / .multi-row-currency carry .side-amount / .side-currency
   (see above) for their actual styling — these two classes are JS selector
   hooks only. */

.remove-row-btn {
  width: 28px;
  height: 28px;
  min-width: 28px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}

.remove-row-btn svg {
  width: 13px;
  height: 13px;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
}

.remove-row-btn:hover,
.remove-row-btn:focus-visible {
  border-color: rgba(224, 133, 133, 0.5);
  color: #e08585;
}

.remove-row-btn[hidden] { display: none; }

/* Invisible, same footprint as .remove-row-btn (28px) — the result row has
   no remove button, but without this spacer its box would render wider
   than the input rows above it (no sibling eating that 28px + gap), which
   shifts its amount/currency divider out of line with theirs. */
.remove-row-btn-spacer {
  display: block;
  width: 28px;
  height: 28px;
  min-width: 28px;
}

.add-row-row {
  display: flex;
  justify-content: flex-start;
  margin-bottom: 14px;
}

/* Same circular treatment as .swap-btn in single mode — sized a notch
   past swap-btn's 38px since this one has no label text next to it. */
.add-row-btn {
  width: 44px;
  height: 44px;
  min-width: 44px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--accent-bright);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.add-row-btn svg {
  width: 20px;
  height: 20px;
  stroke: currentColor;
  fill: none;
  stroke-width: 2.3;
  stroke-linecap: round;
}

.add-row-btn:hover,
.add-row-btn:focus-visible {
  border-color: var(--accent);
  transform: scale(1.08);
}

.multi-arrow-row {
  display: flex;
  justify-content: center;
  margin: 4px 0 16px;
  color: var(--accent-bright);
}

.multi-arrow-row svg {
  width: 30px;
  height: 30px;
  stroke: currentColor;
  fill: none;
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Keyed off .converter-card's own width (container-type:inline-size,
   above) rather than the viewport — see the comment there. 560px is the
   card's own inline-size, not the screen: below it, the 3-part row
   (side + swap button + side, each side needing ~220px) no longer fits
   without an awkward mid-wrap, so it switches to the same stacked layout
   phones get, whether the card is narrow because the screen is a phone or
   because it's sharing a desktop row with another tool. */
@container (max-width: 560px) {
  .converter-row { flex-direction: column; align-items: stretch; }
  /* .converter-side's base rule is `flex: 1 1 220px`, sized for the
     side-by-side row (220px = a sane MIN WIDTH). Once the row above flips
     to flex-direction:column, that same "220px" is read as a min HEIGHT
     instead — every side box was inflating to ~220px tall for what's
     really one line of text. Reset the basis so each box is just as tall
     as its content. */
  .converter-side { max-width: none; flex: 0 1 auto; }
  .swap-btn { align-self: center; transform: rotate(90deg); }
  .swap-btn:hover, .swap-btn:focus-visible { transform: rotate(270deg); }

  .multi-row { flex-wrap: wrap; }
  .multi-row-box { flex-wrap: wrap; }
  .multi-row-box .side-amount { flex: 1 1 100%; }
  .multi-row-box .side-currency {
    flex: 1 1 100%;
    width: auto;
    border-left: none;
    border-top: 1px solid var(--border);
    padding: 8px 0 0;
  }
  .remove-row-btn { flex: 0 0 auto; }
}

footer {
  border-top: 1px solid var(--border);
  padding: 24px 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  color: var(--text-dim);
  font-size: 12.5px;
}

footer a {
  color: var(--text-dim);
  transition: color 0.15s ease;
}

footer a:hover {
  color: var(--accent-bright);
}

@media (max-width: 900px) {
  .navbar {
    gap: 10px;
    padding: 0 14px;
  }
  .nav-links {
    gap: 20px;
  }
  .nav-links a {
    font-size: 13px;
  }
  .hero h1 {
    font-size: 44px;
    letter-spacing: -1.5px;
  }
  .hero .tagline {
    font-size: 18px;
  }
  .story-section,
  .story-section.reverse {
    flex-direction: column;
    text-align: center;
    padding: 64px 24px;
    gap: 32px;
  }
  .story-art { justify-content: center; }
}

/* ---------- Panel (separated section card) ---------- */
.panel {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  clip-path: polygon(0 0, calc(100% - 26px) 0, 100% 26px, 100% 100%, 0 100%);
  overflow: hidden;
}

.panel::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: calc(100% - 26px);
  height: 2px;
  background: linear-gradient(90deg, var(--accent-bright) 0%, rgba(95, 212, 127, 0.5) 35%, transparent 85%);
}

.panel::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(260px circle at var(--mx, 50%) var(--my, 50%), rgba(95, 212, 127, 0.1), transparent 70%);
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
}

.panel:hover::after {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .panel::after { transition: opacity 0.01ms; }
}

/* ---------- Story sections ---------- */
.story-section {
  display: flex;
  align-items: center;
  gap: 56px;
  /* Matches .page-header/.block's 1320px so the homepage body lines up
     with every inner page at the same viewport width. */
  max-width: 1320px;
  margin: 32px auto;
  padding: 64px 48px;
}

.story-section.reverse {
  flex-direction: row-reverse;
}

.story-text {
  flex: 1;
  min-width: 0;
}

.story-text .eyebrow {
  font-family: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--accent-bright);
  margin-bottom: 10px;
}

.story-text h2 {
  font-size: 36px;
  font-weight: 700;
  line-height: 1.18;
  text-wrap: balance;
  margin-bottom: 16px;
}

.story-text p {
  font-size: 15.5px;
  color: var(--text-dim);
  line-height: 1.68;
  max-width: 42ch;
}

.story-art {
  flex: 1;
  display: flex;
  justify-content: center;
  position: relative;
}

.story-art::before {
  content: "";
  position: absolute;
  width: 220px;
  height: 220px;
  background: radial-gradient(circle, rgba(63, 174, 92, 0.28) 0%, rgba(63, 174, 92, 0) 72%);
  filter: blur(4px);
  z-index: 0;
}

.story-svg {
  position: relative;
  z-index: 1;
  width: min(320px, 100%);
  height: auto;
}

.draw-line {
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  animation: drawLine 3.4s ease-in-out infinite;
}

@keyframes drawLine {
  0%   { stroke-dashoffset: 100; }
  55%  { stroke-dashoffset: 0; }
  100% { stroke-dashoffset: 0; }
}

.pulse-dot {
  animation: dotPulse 3.4s ease-in-out infinite;
  transform-box: fill-box;
  transform-origin: center;
}

@keyframes dotPulse {
  0%, 52%  { opacity: 0; transform: scale(0.5); }
  58%      { opacity: 1; transform: scale(1.5); }
  68%, 100% { opacity: 1; transform: scale(1); }
}

.lens-group {
  transform-box: fill-box;
  transform-origin: center;
  animation: lensScan 3.6s ease-in-out infinite;
}

@keyframes lensScan {
  0%, 100% { transform: translate(0, 0); }
  50%      { transform: translate(-8px, 5px); }
}

@media (prefers-reduced-motion: reduce) {
  .draw-line { animation: none; stroke-dashoffset: 0; }
  .pulse-dot { animation: none; opacity: 1; transform: scale(1); }
  .lens-group { animation: none; }
}

/* ---------- Marquee ---------- */
.marquee-section {
  max-width: 1080px;
  margin: 32px auto 48px;
  padding: 56px 0;
  text-align: center;
}

.marquee-section .eyebrow {
  font-family: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--accent-bright);
  margin-bottom: 10px;
}

.marquee-section h2 {
  font-size: 30px;
  font-weight: 700;
  margin-bottom: 40px;
}

.marquee-wrap {
  overflow: hidden;
  width: 100%;
  -webkit-mask-image: linear-gradient(90deg, transparent, black 10%, black 90%, transparent);
  mask-image: linear-gradient(90deg, transparent, black 10%, black 90%, transparent);
}

.marquee-track {
  display: flex;
  gap: 16px;
  width: max-content;
  animation: marqueeScroll 26s linear infinite;
}

@keyframes marqueeScroll {
  from { transform: translateX(-50%); }
  to   { transform: translateX(0%); }
}

@media (prefers-reduced-motion: reduce) {
  .marquee-track { animation: none; transform: translateX(0); }
}

.chip {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 10px 20px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text-dim);
  white-space: nowrap;
}

.chip svg {
  width: 16px;
  height: 16px;
  stroke: var(--accent-bright);
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---------- Closing CTA ---------- */
.cta-band {
  text-align: center;
  padding: 8px 32px 96px;
}

.cta-band p {
  color: var(--text-dim);
  font-size: 15px;
  margin-bottom: 20px;
}

/* ---------- Auth (login / signup) ---------- */
.auth-wrap {
  min-height: calc(100vh - 52px - 74px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px 24px;
}

.auth-card {
  position: relative;
  overflow: hidden;
  width: 100%;
  max-width: 380px;
  background: var(--surface);
  border: 1px solid rgba(95, 212, 127, 0.35);
  border-radius: 12px;
  padding: 34px 30px;
}

/* Cursor-tracked hover glow, same technique as .panel/.tool-card. */
.auth-card::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(260px circle at var(--mx, 50%) var(--my, 50%), rgba(95, 212, 127, 0.12), transparent 70%);
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
}

.auth-card:hover::before {
  opacity: 1;
}

.auth-title {
  font-family: "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 22px;
  font-weight: 700;
  color: var(--accent-bright);
  text-align: center;
}

.auth-subtitle {
  color: var(--text-dim);
  font-size: 13.5px;
  text-align: center;
  margin-top: 6px;
  margin-bottom: 26px;
}

.auth-field {
  display: flex;
  flex-direction: column;
  gap: 7px;
  margin-bottom: 16px;
}

.password-checklist {
  list-style: none;
  margin-top: 2px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.password-checklist li {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 11.5px;
  color: var(--text-dim);
  transition: color 0.15s ease;
}

.password-checklist li::before {
  content: "";
  flex-shrink: 0;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  border: 1.5px solid var(--border-strong);
  transition: border-color 0.15s ease, background 0.15s ease;
}

.password-checklist li.met {
  color: var(--accent-bright);
}

.password-checklist li.met::before {
  content: "✓";
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 9.5px;
  font-weight: 700;
  color: #06120a;
  background: var(--accent-bright);
  border-color: var(--accent-bright);
}

.auth-field label {
  font-family: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-dim);
}

.auth-input {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  width: 100%;
  font-family: inherit;
  font-size: 14.5px;
  color: var(--text);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.auth-input::placeholder { color: var(--text-dim); }

.auth-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(95, 212, 127, 0.15);
}

.auth-submit {
  width: 100%;
  text-align: center;
  border: none;
  cursor: pointer;
  margin-top: 4px;
}

.auth-submit:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
}

.auth-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 22px 0;
  color: var(--text-dim);
  font-size: 12px;
}

.auth-divider::before,
.auth-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

.btn-google {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: #fff;
  color: #1f1f1f;
  font-weight: 600;
  font-size: 14px;
  padding: 11px 20px;
  border-radius: 8px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  cursor: pointer;
  transition: background 0.15s ease, transform 0.15s ease;
}

.btn-google:hover {
  background: #f4f4f4;
  transform: translateY(-1px);
}

.btn-google svg { width: 18px; height: 18px; }

.auth-switch {
  text-align: center;
  margin-top: 22px;
  font-size: 13.5px;
  color: var(--text-dim);
}

.auth-switch a {
  color: var(--accent-bright);
  font-weight: 600;
}

.auth-switch a:hover { text-decoration: underline; }

.auth-message {
  display: none;
  margin-top: 16px;
  padding: 10px 14px;
  border-radius: 8px;
  font-size: 13px;
  line-height: 1.5;
}

.auth-message.is-visible { display: block; }

.auth-message.error {
  background: rgba(176, 64, 64, 0.12);
  border: 1px solid rgba(224, 133, 133, 0.35);
  color: #e08585;
}

.auth-message.success {
  background: rgba(63, 174, 92, 0.1);
  border: 1px solid rgba(95, 212, 127, 0.35);
  color: var(--accent-bright);
}

@media (max-width: 420px) {
  .auth-card { padding: 28px 22px; }
}

/* ---------- Portfolio page ---------- */
.portfolio-section {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 28px 32px;
  margin-bottom: 24px;
}

.portfolio-section-head {
  margin-bottom: 18px;
}

.portfolio-section-head h3 {
  font-family: "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 19px;
  font-weight: 700;
  color: var(--accent-bright);
}

.portfolio-section-sub {
  display: block;
  margin-top: 4px;
  font-size: 13px;
  color: var(--text-dim);
}

.portfolio-table-wrap {
  overflow-x: auto;
  margin-bottom: 20px;
}

.portfolio-table {
  width: 100%;
  border-collapse: collapse;
}

.portfolio-table th {
  text-align: left;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--text-dim);
  padding: 0 14px 10px;
  border-bottom: 1px solid var(--border);
}

.portfolio-table td {
  padding: 12px 14px;
  font-family: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 14px;
  border-bottom: 1px solid var(--border);
}

.portfolio-table tbody tr:last-child td {
  border-bottom: none;
}

.portfolio-table td:last-child {
  width: 1%;
  white-space: nowrap;
  padding-right: 4px;
}

.portfolio-empty {
  display: none;
  padding: 20px 14px;
  text-align: center;
  font-size: 13.5px;
  color: var(--text-dim);
}

.portfolio-empty:not([hidden]) { display: block; }

.portfolio-add-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 14px;
}

.portfolio-add-form .auth-field {
  flex: 1 1 140px;
  margin-bottom: 0;
}

.portfolio-field-ticker { flex-basis: 110px; }
.portfolio-field-currency { flex-basis: 100px; }

.portfolio-add-submit {
  border: none;
  cursor: pointer;
  font-family: inherit;
  white-space: nowrap;
}

.portfolio-error {
  display: none;
  margin-top: 14px;
  font-size: 13px;
  color: #e08585;
}

.portfolio-error.is-visible { display: block; }

@media (max-width: 640px) {
  .portfolio-section { padding: 22px 20px; }
  .portfolio-add-form { flex-direction: column; align-items: stretch; }
  .portfolio-add-form .auth-field { flex-basis: auto; }
  .portfolio-add-submit { width: 100%; }
}

/* ---------- Tools page: Tax Calculator & Cash Flow Projector ---------- */
.tax-card,
.projector-card {
  border-style: solid;
  border-color: rgba(95, 212, 127, 0.45);
  display: block;
  text-align: left;
  /* Top padding matches .converter-card's (22px) on purpose — that's what
     lines up "Tax Calculator" with "Currency Converter" across the two
     cards. The extra height that restores the "Converter = 2 units" ratio
     from CLAUDE.md (lost when the description line under the title was
     removed, see tools.html) goes on the BOTTOM only, so it doesn't push
     the heading down again. Don't rebalance this back to symmetric
     top/bottom padding — that's the bug this comment is here to prevent. */
  padding: 22px 24px 75px;
  min-height: 0;
}

.tool-card-sub {
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-dim);
  margin-top: -10px;
  margin-bottom: 22px;
  max-width: 560px;
}

.calc-form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 14px;
}

.calc-form .auth-field {
  flex: 1 1 140px;
  margin-bottom: 0;
}

.calc-field-country,
.calc-field-frequency,
.calc-field-type { flex-basis: 130px; }
.calc-field-name { flex-basis: 160px; }
.calc-field-amount { flex-basis: 120px; }

.calc-submit {
  border: none;
  cursor: pointer;
  font-family: inherit;
  white-space: nowrap;
}

.calc-error {
  display: none;
  margin-top: 14px;
  font-size: 13px;
  color: #e08585;
}

.calc-error.is-visible { display: block; }

.calc-result {
  margin-top: 20px;
  background: rgba(63, 174, 92, 0.08);
  border: 1px solid rgba(95, 212, 127, 0.3);
  border-radius: 10px;
  padding: 16px 20px;
}

.calc-result-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 14px;
  margin-bottom: 8px;
}

.calc-result-row:last-child { margin-bottom: 0; }

.calc-result-row span { color: var(--text-dim); }

.calc-result-row strong {
  font-family: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 17px;
  color: var(--accent-bright);
}

.calc-table-wrap {
  overflow-x: auto;
  margin-bottom: 20px;
}

.calc-table {
  width: 100%;
  border-collapse: collapse;
}

.calc-table th {
  text-align: left;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--text-dim);
  padding: 0 14px 10px;
  border-bottom: 1px solid var(--border);
}

.calc-table td {
  padding: 12px 14px;
  font-family: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 14px;
  border-bottom: 1px solid var(--border);
}

.calc-table tbody tr:last-child td { border-bottom: none; }
.calc-table td:last-child { width: 1%; white-space: nowrap; padding-right: 4px; }

.calc-empty {
  display: none;
  padding: 20px 14px;
  text-align: center;
  font-size: 13.5px;
  color: var(--text-dim);
}

.calc-empty:not([hidden]) { display: block; }

/* ---------- Gym Schedule page ---------- */
.gym-layout {
  display: flex;
  align-items: flex-start;
  gap: 16px;
}

.gym-schedule-card,
.gym-workout-card {
  /* Same solid-border card look as .converter-card/.tax-card — see the
     design-system rule in CLAUDE.md: new cards reuse the existing card
     style, they don't invent one. */
  border-style: solid;
  border-color: rgba(95, 212, 127, 0.45);
  display: block;
  text-align: left;
  padding: 22px 24px;
  min-height: 0;
}

.gym-schedule-card {
  /* Narrow, fixed-ish column — a day name + one workout label per row
     doesn't need more room than this, and keeping it narrow is what
     leaves .gym-workout-card the rest of the row. */
  flex: 0 0 260px;
}

.gym-workout-card {
  flex: 1 1 420px;
  min-width: 0;
}

.gym-day-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Hidden by default (desktop uses .gym-day-list above); shown only at/below
   the 720px breakpoint, where 7 full day-name rows don't fit this card's
   260px width without wrapping badly. See the 720px media query below. */
.gym-day-circles {
  display: none;
  gap: 6px;
}

.gym-day-btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 14px;
  cursor: pointer;
  font-family: inherit;
  color: var(--text);
  text-align: left;
  transition: border-color 0.15s ease, background 0.15s ease;
}

.gym-day-btn:hover {
  border-color: var(--accent);
}

.gym-day-btn.is-today {
  border-color: rgba(95, 212, 127, 0.35);
}

.gym-day-btn.is-selected {
  background: rgba(63, 174, 92, 0.12);
  border-color: var(--accent);
}

.gym-day-name {
  font-size: 13.5px;
  font-weight: 600;
}

.gym-day-workout {
  font-family: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 11.5px;
  color: var(--text-dim);
}

.gym-day-btn.is-selected .gym-day-workout {
  color: var(--accent-bright);
}

/* Mobile circle variant — same is-today/is-selected classes as the row
   buttons above, but styled as a compact number instead of a name+label
   row, since 7 full rows don't fit at phone width. */
.gym-day-circle {
  flex: 1 1 0;
  max-width: 44px;
  aspect-ratio: 1;
  padding: 0;
  justify-content: center;
  border-radius: 50%;
  font-family: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-weight: 700;
  font-size: 14px;
  color: var(--text-dim);
}

.gym-day-circle.is-today {
  border-color: var(--accent-bright);
  border-width: 2px;
  color: var(--text);
}

.gym-day-circle.is-selected {
  background: var(--accent);
  border-color: var(--accent);
  color: #06120a;
}

.gym-today-badge {
  margin-left: 6px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: #06120a;
  background: var(--accent-bright);
  padding: 2px 6px;
  border-radius: 4px;
  vertical-align: middle;
}

/* Author CSS beats the browser's default [hidden]{display:none} rule once
   any property is set on the same element by class — so display can only
   be turned on here, in a :not([hidden]) rule, never set unconditionally
   above, or every badge would render regardless of the hidden attribute
   (this is the same pattern as .calc-empty:not([hidden]) elsewhere in this
   file — copy it, don't set display directly on a [hidden]-toggled class). */
.gym-today-badge:not([hidden]) {
  display: inline-block;
}

/* The generic .calc-table td:last-child rule (width:1%, nowrap) is meant
   for a single short number — the PR column holds "100kg x 5 · 11 Sep"
   plus an edit button, so it needs its own sizing instead. */
#exerciseTable td:last-child {
  width: auto;
  white-space: normal;
  padding-right: 14px;
}

.pr-cell {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.pr-value {
  color: var(--text-dim);
}

.pr-edit-btn {
  background: none;
  border: none;
  color: var(--text-dim);
  cursor: pointer;
  font-size: 13px;
  line-height: 1;
  padding: 4px 6px;
  border-radius: 6px;
  transition: background 0.15s ease, color 0.15s ease;
}

.pr-edit-btn:hover {
  background: var(--surface-2);
  color: var(--accent-bright);
}

.pr-input {
  max-width: 150px;
  padding: 6px 10px;
  font-size: 13px;
}

.gym-running-note {
  padding: 16px 20px;
  background: rgba(63, 174, 92, 0.08);
  border: 1px solid rgba(95, 212, 127, 0.3);
  border-radius: 10px;
  font-size: 13.5px;
  color: var(--text-dim);
}

@media (max-width: 720px) {
  .gym-layout { flex-direction: column; }
  .gym-schedule-card,
  .gym-workout-card { flex-basis: auto; width: 100%; }
  /* Swap the day-name list for the number-circle row — see the comments
     on .gym-day-list / .gym-day-circles above. */
  .gym-day-list { display: none; }
  .gym-day-circles { display: flex; }
}

@media (max-width: 640px) {
  .gym-schedule-card,
  .gym-workout-card { padding: 22px 20px; }
  .pr-input { max-width: 120px; }
}

.projector-horizon-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 14px;
  margin-top: 4px;
  margin-bottom: 20px;
  padding-top: 20px;
  border-top: 1px dashed var(--border);
}

.projector-horizon-row .auth-field {
  flex: 1 1 140px;
  margin-bottom: 0;
}

.projector-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  margin-bottom: 20px;
}

.projector-summary[hidden] { display: none; }

.projector-summary-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.projector-summary-item span {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--text-dim);
}

.projector-summary-item strong {
  font-family: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 18px;
  color: var(--accent-bright);
}

/* ---------- Projects page ---------- */
.feasibility-banner {
  margin-top: 20px;
  margin-bottom: 20px;
  padding: 14px 18px;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 600;
}

.feasibility-banner[hidden] { display: none; }

.feasibility-banner.is-good {
  background: rgba(63, 174, 92, 0.1);
  border: 1px solid rgba(95, 212, 127, 0.35);
  color: var(--accent-bright);
}

.feasibility-banner.is-bad {
  background: rgba(176, 64, 64, 0.12);
  border: 1px solid rgba(224, 133, 133, 0.35);
  color: #e08585;
}

.project-card {
  border-color: rgba(95, 212, 127, 0.2);
}

.project-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.project-card .calc-form {
  margin-top: 4px;
}

@media (max-width: 640px) {
  .tax-card,
  .projector-card { padding: 22px 20px; }
  .calc-form,
  .projector-horizon-row { flex-direction: column; align-items: stretch; }
  .calc-form .auth-field,
  .projector-horizon-row .auth-field { flex-basis: auto; }
  .calc-submit { width: 100%; }
}

/* ---------- Navbar "Portfolio" hover dropdown ---------- */
/* Single-column flyout under the Portfolio nav tab — Summary / Holdings.
   Shared markup across every page (see the nav in any .html file). */
.nav-item-dropdown {
  position: relative;
}

.nav-dropdown-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: 0 0 10px 10px;
  padding: 6px;
  box-shadow: 0 14px 32px rgba(0, 0, 0, 0.4);
  z-index: 150;
}

.nav-item-dropdown:hover .nav-dropdown-menu,
.nav-item-dropdown:focus-within .nav-dropdown-menu {
  display: block;
}

.nav-dropdown-option {
  display: block;
  padding: 9px 12px;
  border-radius: 6px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  transition: color 0.15s ease, background 0.15s ease;
}

.nav-dropdown-option:hover,
.nav-dropdown-option:focus-visible {
  color: var(--accent-bright);
  background: rgba(63, 174, 92, 0.12);
  outline: none;
}

/* ---------- Mobile nav (hamburger + tap-to-expand submenus) ---------- */
/* Hidden on desktop; the >900px layout above (hover dropdowns, all tabs
   visible in a row) is unchanged. Below 900px, .nav-toggle appears and
   .nav-links collapses into a panel that nav-mobile.js opens/closes by
   toggling .is-open — same pattern used for the profile dropdown. */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 7px;
  color: var(--nav-text);
  background: none;
  border: none;
  cursor: pointer;
  transition: color 0.18s ease, background 0.18s ease;
}

.nav-toggle svg {
  width: 20px;
  height: 20px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
}

.nav-toggle:hover,
.nav-toggle:focus-visible {
  color: var(--accent-bright);
  background: rgba(63, 174, 92, 0.1);
}

.nav-dropdown-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 40px;
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--nav-text);
  cursor: pointer;
}

.nav-dropdown-toggle svg {
  width: 16px;
  height: 16px;
  stroke: currentColor;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.18s ease;
}

.nav-item-dropdown.is-open .nav-dropdown-toggle svg {
  transform: rotate(180deg);
}

@media (max-width: 900px) {
  .nav-toggle {
    display: flex;
  }

  .nav-right {
    margin-left: auto;
  }

  .nav-links {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    align-self: auto;
    background: var(--surface);
    border-bottom: 1px solid var(--border-strong);
    box-shadow: 0 14px 32px rgba(0, 0, 0, 0.4);
    z-index: 150;
    max-height: calc(100vh - 52px);
    overflow-y: auto;
  }

  .nav-links.is-open {
    display: flex;
  }

  .nav-links li {
    flex: none;
  }

  .nav-links li:not(:last-child) {
    border-right: none;
    border-bottom: 1px solid var(--border);
  }

  .nav-links a {
    justify-content: flex-start;
    padding: 14px 18px;
  }

  .nav-item-dropdown {
    display: flex;
    align-items: stretch;
    flex-wrap: wrap;
  }

  .nav-item-dropdown > a {
    flex: 1;
  }

  .nav-dropdown-toggle {
    display: flex;
  }

  /* Hover/focus-within no longer opens the submenu at this width — the
     chevron button (via nav-mobile.js) is the only way in, so it doesn't
     fight a stray touch-hover state. */
  .nav-item-dropdown:hover .nav-dropdown-menu,
  .nav-item-dropdown:focus-within .nav-dropdown-menu {
    display: none;
  }

  .nav-item-dropdown.is-open .nav-dropdown-menu {
    display: block;
  }

  .nav-dropdown-menu {
    position: static;
    width: 100%;
    border: none;
    border-radius: 0;
    box-shadow: none;
    background: var(--surface-2);
    padding: 0;
  }

  .nav-dropdown-option {
    padding: 12px 18px 12px 30px;
    border-radius: 0;
  }
}

.portfolio-summary-placeholder {
  padding: 28px 14px;
  text-align: center;
  font-size: 13.5px;
  color: var(--text-dim);
}

.portfolio-actions-cell {
  display: flex;
  align-items: center;
  gap: 8px;
}

.portfolio-details-btn {
  display: inline-flex;
  align-items: center;
  padding: 5px 10px;
  border-radius: 6px;
  background: rgba(63, 174, 92, 0.14);
  color: var(--accent-bright);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  transition: background 0.15s ease, color 0.15s ease;
}

.portfolio-details-btn:hover,
.portfolio-details-btn:focus-visible {
  background: var(--accent-bright);
  color: #06120a;
  outline: none;
}

